xref: /aosp_15_r20/external/google-styleguide/angularjs-google-style.html (revision 8c35d5ee8e2913d4bd6623e2b93232b1da0ab719)
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&lt;div ng-controller="hello.mainpage.HomeCtrl"/&gt;
197*8c35d5eeSXin Li  &lt;span ng-class="homeCtrl.myColor"&gt;I'm in a color!&lt;/span&gt;
198*8c35d5eeSXin Li  &lt;span&gt;{{homeCtrl.add(5, 6)}}&lt;/span&gt;
199*8c35d5eeSXin Li&lt;/div&gt;
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&lt;div ng-controller="hello.mainpage.HomeCtrl as homeCtrl"/&gt;
238*8c35d5eeSXin Li  &lt;span ng-class="homeCtrl.myColor"&gt;I'm in a color!&lt;/span&gt;
239*8c35d5eeSXin Li  &lt;span&gt;{{homeCtrl.add(5, 6)}}&lt;/span&gt;
240*8c35d5eeSXin Li&lt;/div&gt;
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>&lt;ng-include src="template"&gt;&lt;/ng-include&gt;</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