1*8c35d5eeSXin Li 2*8c35d5eeSXin Li<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "https://www.w3.org/TR/REC-html40/strict.dtd"> 3*8c35d5eeSXin Li<html> 4*8c35d5eeSXin Li<head> 5*8c35d5eeSXin Li <META http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> 6*8c35d5eeSXin Li <base target="_blank"> 7*8c35d5eeSXin Li <link rel="stylesheet" type="text/css" href="styleguide.css"> 8*8c35d5eeSXin Li <script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"></script> 9*8c35d5eeSXin Li <script language="javascript" src="/eng/doc/devguide/include/styleguide.js"></script> 10*8c35d5eeSXin Li <title>Google's AngularJS Style Guide</title> 11*8c35d5eeSXin Li <style type="text/css"><!-- 12*8c35d5eeSXin Li th { background-color: #ddd; } 13*8c35d5eeSXin Li //--></style> 14*8c35d5eeSXin Li</head> 15*8c35d5eeSXin Li<body onload="prettyPrint();initStyleGuide();"> 16*8c35d5eeSXin Li<h1 class="external">An AngularJS Style Guide for Closure Users at Google</h1> 17*8c35d5eeSXin Li 18*8c35d5eeSXin Li<p class="external">This is the external version of a document that was primarily written for Google 19*8c35d5eeSXin Li engineers. It describes a recommended style for AngularJS apps that use Closure, as used 20*8c35d5eeSXin Li internally at Google. Members of the broader AngularJS community should feel free to apply 21*8c35d5eeSXin Li (or not apply) these recommendations, as relevant to their own use cases.</p> 22*8c35d5eeSXin Li 23*8c35d5eeSXin Li<p class="external">This document describes style for AngularJS apps in google3. This guide 24*8c35d5eeSXin Li supplements and extends the <a href="https://google.github.io/styleguide/jsguide.html"> 25*8c35d5eeSXin Li Google JavaScript Style Guide</a>. 26*8c35d5eeSXin Li</p> 27*8c35d5eeSXin Li 28*8c35d5eeSXin Li<p><b>Style Note</b>: Examples on the AngularJS external webpage, and many external apps, are 29*8c35d5eeSXin Li written in a style that freely uses closures, favors functional inheritance, and does not often use 30*8c35d5eeSXin Li <a class="external" 31*8c35d5eeSXin Li href="https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System"> 32*8c35d5eeSXin Li JavaScript types</a>. Google follows a more rigorous Javascript style to support JSCompiler 33*8c35d5eeSXin Li optimizations and large code bases - see the javascript-style mailing list. 34*8c35d5eeSXin Li This is not an Angular-specific issue, and is not discussed further in this style guide. 35*8c35d5eeSXin Li (But if you want further reading: 36*8c35d5eeSXin Li <a href="http://martinfowler.com/bliki/Lambda.html">Martin Fowler on closures</a>, 37*8c35d5eeSXin Li <a href="http://jibbering.com/faq/notes/closures/">much longer description</a>, appendix A of the 38*8c35d5eeSXin Li <a href="https://books.google.com/books/about/Closure_The_Definitive_Guide.html?id=p7uyWPcVGZsC"> 39*8c35d5eeSXin Li closure book</a> has a good description of inheritance patterns and why it prefers 40*8c35d5eeSXin Li pseudoclassical, 41*8c35d5eeSXin Li <a href="https://books.google.com/books/about/JavaScript.html?id=PXa2bby0oQ0C"> 42*8c35d5eeSXin Li Javascript, the Good Parts</a> as a counter.)</p> 43*8c35d5eeSXin Li 44*8c35d5eeSXin Li<h5>1 Angular Language Rules</h5> 45*8c35d5eeSXin Li<ul> 46*8c35d5eeSXin Li <li> <a target="_self" href="#googprovide">Manage dependencies with Closure's goog.require and 47*8c35d5eeSXin Li goog.provide</a> 48*8c35d5eeSXin Li <li> <a target="_self" href="#modules"> Modules</a> 49*8c35d5eeSXin Li <li> <a target="_self" href="#moduledeps"> Modules should reference other modules using the 50*8c35d5eeSXin Li "name" property</a> 51*8c35d5eeSXin Li <li> <a target="_self" href="#externs">Use the provided Angular externs file</a> 52*8c35d5eeSXin Li <li> <a target="_self" href="#compilerflags">JSCompiler Flags</a> 53*8c35d5eeSXin Li <li> <a target="_self" href="#controllers">Controllers and Scopes</a> 54*8c35d5eeSXin Li <li> <a target="_self" href="#directives">Directives</a> 55*8c35d5eeSXin Li <li> <a target="_self" href="#services">Services</a> 56*8c35d5eeSXin Li</ul> 57*8c35d5eeSXin Li<h5>2 Angular Style Rules</h5> 58*8c35d5eeSXin Li<ul> 59*8c35d5eeSXin Li <li><a target="_self" href="#dollarsign">Reserve $ for Angular properties and services 60*8c35d5eeSXin Li </a> 61*8c35d5eeSXin Li <li><a target="_self" href="#customelements">Custom elements.</a> 62*8c35d5eeSXin Li</ul> 63*8c35d5eeSXin Li<h5>3 Angular Tips, Tricks, and Best Practices</h5> 64*8c35d5eeSXin Li<ul> 65*8c35d5eeSXin Li <li><a target="_self" href="#testing">Testing</a> 66*8c35d5eeSXin Li <li><a target="_self" href="#appstructure">Consider using the Best Practices for App Structure</a> 67*8c35d5eeSXin Li <li><a target="_self" href="#scopeinheritance">Be aware of how scope inheritance works</a> 68*8c35d5eeSXin Li <li><a target="_self" href="#nginject">Use @ngInject for easy dependency injection compilation</a> 69*8c35d5eeSXin Li</ul> 70*8c35d5eeSXin Li 71*8c35d5eeSXin Li<h5><a target="_self" href="#bestpractices">4 Best practices links and docs</a></h5> 72*8c35d5eeSXin Li 73*8c35d5eeSXin Li<h2>1 Angular Language Rules</h2> 74*8c35d5eeSXin Li 75*8c35d5eeSXin Li<h3 id="googprovide">Manage dependencies with Closure's goog.require and goog.provide</h3> 76*8c35d5eeSXin Li<p>Choose a namespace for your project, and use goog.provide and goog.require.</p> 77*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 78*8c35d5eeSXin Ligoog.provide('hello.about.AboutCtrl'); 79*8c35d5eeSXin Ligoog.provide('hello.versions.Versions'); 80*8c35d5eeSXin Li</pre> 81*8c35d5eeSXin Li 82*8c35d5eeSXin Li<p><b>Why?</b> 83*8c35d5eeSXin Li Google BUILD rules integrate nicely with closure provide/require.</p> 84*8c35d5eeSXin Li 85*8c35d5eeSXin Li<h3 id="modules">Modules</h3> 86*8c35d5eeSXin Li 87*8c35d5eeSXin Li<p>Your main application module should be in your root client directory. A module should never be 88*8c35d5eeSXin Li altered other than the one where it is defined.</p> 89*8c35d5eeSXin Li 90*8c35d5eeSXin Li<p>Modules may either be defined in the same file as their components (this works well for a module 91*8c35d5eeSXin Li that contains exactly one service) or in a separate file for wiring pieces together.</p> 92*8c35d5eeSXin Li 93*8c35d5eeSXin Li<p><b>Why?</b> 94*8c35d5eeSXin Li A module should be consistent for anyone that wants to include it as a reusable component. 95*8c35d5eeSXin Li If a module can mean different things depending on which files are included, it is not consistent. 96*8c35d5eeSXin Li</p> 97*8c35d5eeSXin Li 98*8c35d5eeSXin Li<h3 id="moduledeps"> 99*8c35d5eeSXin Li Modules should reference other modules using the Angular Module's "name" property 100*8c35d5eeSXin Li</h3> 101*8c35d5eeSXin Li 102*8c35d5eeSXin Li<p>For example:</p> 103*8c35d5eeSXin Li 104*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 105*8c35d5eeSXin Li// file submodulea.js: 106*8c35d5eeSXin Li goog.provide('my.submoduleA'); 107*8c35d5eeSXin Li 108*8c35d5eeSXin Li my.submoduleA = angular.module('my.submoduleA', []); 109*8c35d5eeSXin Li // ... 110*8c35d5eeSXin Li 111*8c35d5eeSXin Li// file app.js 112*8c35d5eeSXin Li goog.require('my.submoduleA'); 113*8c35d5eeSXin Li 114*8c35d5eeSXin Li Yes: my.application.module = angular.module('hello', [my.submoduleA.name]); 115*8c35d5eeSXin Li <font color="red"> 116*8c35d5eeSXin Li No: my.application.module = angular.module('hello', ['my.submoduleA']); 117*8c35d5eeSXin Li </font></pre> 118*8c35d5eeSXin Li 119*8c35d5eeSXin Li<p><b>Why?</b> 120*8c35d5eeSXin Li Using a property of my.submoduleA prevents Closure presubmit failures complaining that the file is 121*8c35d5eeSXin Li required but never used. Using the .name property avoids duplicating strings.</p> 122*8c35d5eeSXin Li 123*8c35d5eeSXin Li<h3 id="externs">Use a common externs file</h3> 124*8c35d5eeSXin Li 125*8c35d5eeSXin Li<p>This maximally allows the JS compiler to enforce type safety in the presence of externally 126*8c35d5eeSXin Li provided types from Angular, and means you don't have to worry about Angular vars being obfuscated 127*8c35d5eeSXin Li in a confusing way. </p> 128*8c35d5eeSXin Li 129*8c35d5eeSXin Li<p>Note to readers outside Google: the current externs file is located in an internal-to-Google 130*8c35d5eeSXin Li directory, but an example can be found on github <a href="https://github.com/angular/angular.js/pull/4722"> 131*8c35d5eeSXin Li here</a>.</p> 132*8c35d5eeSXin Li 133*8c35d5eeSXin Li<h3 id="compilerflags">JSCompiler Flags</h3> 134*8c35d5eeSXin Li<p><b>Reminder</b>: According to the JS style guide, customer facing code must be compiled.</p> 135*8c35d5eeSXin Li 136*8c35d5eeSXin Li<p><b>Recommended</b>: Use the JSCompiler (the closure compiler that works with js_binary by 137*8c35d5eeSXin Li default) and ANGULAR_COMPILER_FLAGS_FULL from //javascript/angular/build_defs/build_defs for 138*8c35d5eeSXin Li your base flags. 139*8c35d5eeSXin Li</p> 140*8c35d5eeSXin Li 141*8c35d5eeSXin Li<p>Note - if you are using @export for methods, you will need to add the compiler flag</p> 142*8c35d5eeSXin Li<pre> 143*8c35d5eeSXin Li"--generate_exports", 144*8c35d5eeSXin Li</pre> 145*8c35d5eeSXin Li 146*8c35d5eeSXin Li<p>If you are using @export for properties, you will need to add the flags:</p> 147*8c35d5eeSXin Li<pre> 148*8c35d5eeSXin Li"--generate_exports", 149*8c35d5eeSXin Li"--remove_unused_prototype_props_in_externs=false", 150*8c35d5eeSXin Li"--export_local_property_definitions", 151*8c35d5eeSXin Li</pre> 152*8c35d5eeSXin Li 153*8c35d5eeSXin Li<h3 id="controllers">Controllers and Scopes</h3> 154*8c35d5eeSXin Li<p>Controllers are classes. Methods should be defined on MyCtrl.prototype.</p> 155*8c35d5eeSXin Li 156*8c35d5eeSXin Li<p>Google Angular applications should use the <b>'controller as'</b> style to export the controller 157*8c35d5eeSXin Li onto the scope. This is fully implemented in Angular 1.2 and can be mimicked in pre-Angular 1.2 158*8c35d5eeSXin Li builds. 159*8c35d5eeSXin Li</p> 160*8c35d5eeSXin Li 161*8c35d5eeSXin Li<p>Pre Angular 1.2, this looks like:</p> 162*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 163*8c35d5eeSXin Li/** 164*8c35d5eeSXin Li * Home controller. 165*8c35d5eeSXin Li * 166*8c35d5eeSXin Li * @param {!angular.Scope} $scope 167*8c35d5eeSXin Li * @constructor 168*8c35d5eeSXin Li * @ngInject 169*8c35d5eeSXin Li * @export 170*8c35d5eeSXin Li */ 171*8c35d5eeSXin Lihello.mainpage.HomeCtrl = function($scope) { 172*8c35d5eeSXin Li /** @export */ 173*8c35d5eeSXin Li $scope.homeCtrl = this; // This is a bridge until Angular 1.2 controller-as 174*8c35d5eeSXin Li 175*8c35d5eeSXin Li /** 176*8c35d5eeSXin Li * @type {string} 177*8c35d5eeSXin Li * @export 178*8c35d5eeSXin Li */ 179*8c35d5eeSXin Li this.myColor = 'blue'; 180*8c35d5eeSXin Li}; 181*8c35d5eeSXin Li 182*8c35d5eeSXin Li 183*8c35d5eeSXin Li/** 184*8c35d5eeSXin Li * @param {number} a 185*8c35d5eeSXin Li * @param {number} b 186*8c35d5eeSXin Li * @export 187*8c35d5eeSXin Li */ 188*8c35d5eeSXin Lihello.mainpage.HomeCtrl.prototype.add = function(a, b) { 189*8c35d5eeSXin Li return a + b; 190*8c35d5eeSXin Li}; 191*8c35d5eeSXin Li</pre> 192*8c35d5eeSXin Li 193*8c35d5eeSXin Li<p>And the template:</p> 194*8c35d5eeSXin Li 195*8c35d5eeSXin Li<pre> 196*8c35d5eeSXin Li<div ng-controller="hello.mainpage.HomeCtrl"/> 197*8c35d5eeSXin Li <span ng-class="homeCtrl.myColor">I'm in a color!</span> 198*8c35d5eeSXin Li <span>{{homeCtrl.add(5, 6)}}</span> 199*8c35d5eeSXin Li</div> 200*8c35d5eeSXin Li</pre> 201*8c35d5eeSXin Li 202*8c35d5eeSXin Li<p>After Angular 1.2, this looks like:</p> 203*8c35d5eeSXin Li 204*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 205*8c35d5eeSXin Li/** 206*8c35d5eeSXin Li * Home controller. 207*8c35d5eeSXin Li * 208*8c35d5eeSXin Li * @constructor 209*8c35d5eeSXin Li * @ngInject 210*8c35d5eeSXin Li * @export 211*8c35d5eeSXin Li */ 212*8c35d5eeSXin Lihello.mainpage.HomeCtrl = function() { 213*8c35d5eeSXin Li /** 214*8c35d5eeSXin Li * @type {string} 215*8c35d5eeSXin Li * @export 216*8c35d5eeSXin Li */ 217*8c35d5eeSXin Li this.myColor = 'blue'; 218*8c35d5eeSXin Li}; 219*8c35d5eeSXin Li 220*8c35d5eeSXin Li 221*8c35d5eeSXin Li/** 222*8c35d5eeSXin Li * @param {number} a 223*8c35d5eeSXin Li * @param {number} b 224*8c35d5eeSXin Li * @export 225*8c35d5eeSXin Li */ 226*8c35d5eeSXin Lihello.mainpage.HomeCtrl.prototype.add = function(a, b) { 227*8c35d5eeSXin Li return a + b; 228*8c35d5eeSXin Li}; 229*8c35d5eeSXin Li</pre> 230*8c35d5eeSXin Li 231*8c35d5eeSXin Li<p>If you are compiling with property renaming, expose properties and methods using the @export 232*8c35d5eeSXin Li annotation. Remember to @export the constructor as well.</p> 233*8c35d5eeSXin Li 234*8c35d5eeSXin Li<p>And in the template:</p> 235*8c35d5eeSXin Li 236*8c35d5eeSXin Li<pre> 237*8c35d5eeSXin Li<div ng-controller="hello.mainpage.HomeCtrl as homeCtrl"/> 238*8c35d5eeSXin Li <span ng-class="homeCtrl.myColor">I'm in a color!</span> 239*8c35d5eeSXin Li <span>{{homeCtrl.add(5, 6)}}</span> 240*8c35d5eeSXin Li</div> 241*8c35d5eeSXin Li</pre> 242*8c35d5eeSXin Li 243*8c35d5eeSXin Li<p><b>Why?</b> 244*8c35d5eeSXin Li Putting methods and properties directly onto the controller, instead of building up a scope 245*8c35d5eeSXin Li object, fits better with the Google Closure class style. Additionally, using 'controller as' 246*8c35d5eeSXin Li makes it obvious which controller you are accessing when multiple controllers apply to an element. 247*8c35d5eeSXin Li Since there is always a '.' in the bindings, you don't have to worry about prototypal inheritance 248*8c35d5eeSXin Li masking primitives.</p> 249*8c35d5eeSXin Li 250*8c35d5eeSXin Li<h3 id="directives">Directives</h3> 251*8c35d5eeSXin Li 252*8c35d5eeSXin Li<p>All DOM manipulation should be done inside directives. Directives should be kept small and use 253*8c35d5eeSXin Li composition. Files defining directives should goog.provide a static function which returns the 254*8c35d5eeSXin Li directive definition object.</p> 255*8c35d5eeSXin Li 256*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 257*8c35d5eeSXin Ligoog.provide('hello.pane.paneDirective'); 258*8c35d5eeSXin Li 259*8c35d5eeSXin Li/** 260*8c35d5eeSXin Li * Description and usage 261*8c35d5eeSXin Li * @return {angular.Directive} Directive definition object. 262*8c35d5eeSXin Li */ 263*8c35d5eeSXin Lihello.pane.paneDirective = function() { 264*8c35d5eeSXin Li // ... 265*8c35d5eeSXin Li}; 266*8c35d5eeSXin Li</pre> 267*8c35d5eeSXin Li 268*8c35d5eeSXin Li<p><b>Exception</b>: DOM manipulation may occur in services for DOM elements disconnected from the 269*8c35d5eeSXin Li rest of the view, e.g. dialogs or keyboard shortcuts.</p> 270*8c35d5eeSXin Li 271*8c35d5eeSXin Li<h3 id="services">Services</h3> 272*8c35d5eeSXin Li 273*8c35d5eeSXin Li<p>Services registered on the module with <code>module.service</code> are classes. 274*8c35d5eeSXin Li Use <code>module.service</code> instead of <code>module.provider</code> or 275*8c35d5eeSXin Li <code>module.factory</code> unless you need to do initialization beyond just creating a 276*8c35d5eeSXin Li new instance of the class.</p> 277*8c35d5eeSXin Li 278*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 279*8c35d5eeSXin Li/** 280*8c35d5eeSXin Li * @param {!angular.$http} $http The Angular http service. 281*8c35d5eeSXin Li * @constructor 282*8c35d5eeSXin Li */ 283*8c35d5eeSXin Lihello.request.Request = function($http) { 284*8c35d5eeSXin Li /** @type {!angular.$http} */ 285*8c35d5eeSXin Li this.http_ = $http; 286*8c35d5eeSXin Li}; 287*8c35d5eeSXin Li 288*8c35d5eeSXin Lihello.request.Request.prototype.get = function() {/*...*/}; 289*8c35d5eeSXin Li</pre> 290*8c35d5eeSXin Li 291*8c35d5eeSXin Li<p>In the module:</p> 292*8c35d5eeSXin Li 293*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 294*8c35d5eeSXin Limodule.service('request', hello.request.Request); 295*8c35d5eeSXin Li</pre> 296*8c35d5eeSXin Li 297*8c35d5eeSXin Li 298*8c35d5eeSXin Li<h2>2 Angular Style Rules</h2> 299*8c35d5eeSXin Li 300*8c35d5eeSXin Li<h3 id="dollarsign">Reserve $ for Angular properties and services</h3> 301*8c35d5eeSXin Li<p>Do not use $ to prepend your own object properties and service identifiers. Consider this style 302*8c35d5eeSXin Li of naming reserved by AngularJS and jQuery.</p> 303*8c35d5eeSXin Li 304*8c35d5eeSXin Li<p>Yes:</p> 305*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 306*8c35d5eeSXin Li $scope.myModel = { value: 'foo' } 307*8c35d5eeSXin Li myModule.service('myService', function() { /*...*/ }); 308*8c35d5eeSXin Li var MyCtrl = function($http) {this.http_ = $http;}; 309*8c35d5eeSXin Li</pre> 310*8c35d5eeSXin Li 311*8c35d5eeSXin Li<p><font color="red">No:</font></p> 312*8c35d5eeSXin Li<pre class="prettyprint"> 313*8c35d5eeSXin Li $scope.$myModel = { value: 'foo' } // BAD 314*8c35d5eeSXin Li $scope.myModel = { $value: 'foo' } // BAD 315*8c35d5eeSXin Li myModule.service('$myService', function() { ... }); // BAD 316*8c35d5eeSXin Li var MyCtrl = function($http) {this.$http_ = $http;}; // BAD 317*8c35d5eeSXin Li</pre> 318*8c35d5eeSXin Li 319*8c35d5eeSXin Li<p><b>Why?</b> 320*8c35d5eeSXin Li It's useful to distinguish between Angular / jQuery builtins and things you add yourself. 321*8c35d5eeSXin Li In addition, $ is not an acceptable character for variables names in the JS style guide. 322*8c35d5eeSXin Li</p> 323*8c35d5eeSXin Li 324*8c35d5eeSXin Li<h3 id="customelements">Custom elements</h3> 325*8c35d5eeSXin Li 326*8c35d5eeSXin Li<p>For custom elements (e.g. <code><ng-include src="template"></ng-include></code>), IE8 327*8c35d5eeSXin Li requires special support (html5shiv-like hacks) to enable css styling. Be aware of this 328*8c35d5eeSXin Li restriction in apps targeting old versions of IE.</p> 329*8c35d5eeSXin Li 330*8c35d5eeSXin Li<h2>3 Angular Tips, Tricks, and Best Practices</h2> 331*8c35d5eeSXin Li 332*8c35d5eeSXin Li<p>These are not strict style guide rules, but are placed here as reference for folks getting 333*8c35d5eeSXin Li started with Angular at Google.</p> 334*8c35d5eeSXin Li 335*8c35d5eeSXin Li<h3 id="testing">Testing</h3> 336*8c35d5eeSXin Li 337*8c35d5eeSXin Li<p>Angular is designed for test-driven development.</p> 338*8c35d5eeSXin Li 339*8c35d5eeSXin Li<p>The recommended unit testing setup is Jasmine + Karma (though you could use closure tests 340*8c35d5eeSXin Li or js_test)</p> 341*8c35d5eeSXin Li 342*8c35d5eeSXin Li<p>Angular provides easy adapters to load modules and use the injector in Jasmine tests. 343*8c35d5eeSXin Li<ul> 344*8c35d5eeSXin Li <li><a href = "https://docs.angularjs.org/api/angular.mock.module">module</a> 345*8c35d5eeSXin Li <li><a href="https://docs.angularjs.org/api/angular.mock.inject">inject</a> 346*8c35d5eeSXin Li</ul> 347*8c35d5eeSXin Li</p> 348*8c35d5eeSXin Li 349*8c35d5eeSXin Li 350*8c35d5eeSXin Li<h3 id="appstructure">Consider using the Best Practices for App Structure</h3> 351*8c35d5eeSXin Li<p> 352*8c35d5eeSXin Li This <a href="https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub">directory structure doc</a> describes how to structure your application with controllers in 353*8c35d5eeSXin Li nested subdirectories and all components (e.g. services and directives) in a 'components' dir. 354*8c35d5eeSXin Li</p> 355*8c35d5eeSXin Li 356*8c35d5eeSXin Li 357*8c35d5eeSXin Li<h3 id="scopeinheritance">Be aware of how scope inheritance works</h3> 358*8c35d5eeSXin Li 359*8c35d5eeSXin Li<p>See <a href="https://github.com/angular/angular.js/wiki/Understanding-Scopes#wiki-JSproto"> 360*8c35d5eeSXin Li The Nuances of Scope Prototypal Inheritance</a></p> 361*8c35d5eeSXin Li 362*8c35d5eeSXin Li<h3 id="nginject">Use @ngInject for easy dependency injection compilation</h3> 363*8c35d5eeSXin Li<p>This removes the need to add <code>myCtrl['$inject'] = ...</code> to prevent minification from 364*8c35d5eeSXin Li messing up Angular's dependency injection.</p> 365*8c35d5eeSXin Li 366*8c35d5eeSXin Li<p>Usage:</p> 367*8c35d5eeSXin Li<pre class="prettyprint lang-js"> 368*8c35d5eeSXin Li/** 369*8c35d5eeSXin Li * My controller. 370*8c35d5eeSXin Li * @param {!angular.$http} $http 371*8c35d5eeSXin Li * @param {!my.app.myService} myService 372*8c35d5eeSXin Li * @constructor 373*8c35d5eeSXin Li * @export 374*8c35d5eeSXin Li * @ngInject 375*8c35d5eeSXin Li */ 376*8c35d5eeSXin Limy.app.MyCtrl = function($http, myService) { 377*8c35d5eeSXin Li //... 378*8c35d5eeSXin Li}; 379*8c35d5eeSXin Li</pre> 380*8c35d5eeSXin Li 381*8c35d5eeSXin Li<h2 id="bestpractices">4 Best practices links and docs</h2> 382*8c35d5eeSXin Li 383*8c35d5eeSXin Li<ul> 384*8c35d5eeSXin Li <li><a href="https://github.com/angular/angular.js/wiki/Best-Practices"> 385*8c35d5eeSXin Li Best Practices</a> from Angular on GitHub</li> 386*8c35d5eeSXin Li <li><a href="https://www.youtube.com/watch?v=ZhfUv0spHCY"> 387*8c35d5eeSXin Li Meetup video</a> (not Google specific)</li> 388*8c35d5eeSXin Li</ul> 389*8c35d5eeSXin Li<address> 390*8c35d5eeSXin Li Last modified Feb 07 2013 391*8c35d5eeSXin Li</address> 392*8c35d5eeSXin Li</body> 393*8c35d5eeSXin Li<html> 394