|
4 | 4 |
|
5 | 5 | #FAQ
|
6 | 6 |
|
| 7 | +## Questions |
| 8 | + |
7 | 9 | ### Why is this project called "AngularJS"? Why is the namespace called "ng"?
|
8 | 10 |
|
9 | 11 | Because HTML has Angular brackets and "ng" sounds like "Angular".
|
@@ -96,3 +98,100 @@ AJAX Apps}".
|
96 | 98 | ### How is Angular licensed?
|
97 | 99 |
|
98 | 100 | The MIT License.
|
| 101 | + |
| 102 | + |
| 103 | +## Common Pitfalls |
| 104 | + |
| 105 | +The Angular support channel (#angularjs on Freenode) sees a number of recurring pitfalls that new users of Angular fall into. |
| 106 | +This document aims to point them out before you discover them the hard way. |
| 107 | + |
| 108 | +### DOM Manipulation |
| 109 | + |
| 110 | +Stop trying to use jQuery to modify the DOM in controllers. Really. |
| 111 | +That includes adding elements, removing elements, retrieving their contents, showing and hiding them. |
| 112 | +Use built-in directives, or write your own where necessary, to do your DOM manipulation. |
| 113 | +See below about duplicating functionality. |
| 114 | + |
| 115 | +If you're struggling to break the habit, consider removing jQuery from your app. |
| 116 | +Really. Angular has the $http service and powerful directives that make it almost always unnecessary. |
| 117 | +Angular's bundled jQLite has a handful of the features most commonly used in writing Angular directives, especially binding to events. |
| 118 | + |
| 119 | +### Trying to duplicate functionality that already exists |
| 120 | + |
| 121 | +There's a good chance that your app isn't the first to require certain functionality. |
| 122 | +There are a few pieces of Angular that are particularly likely to be reimplemented out of old habits. |
| 123 | + |
| 124 | +**ng-repeat** |
| 125 | + |
| 126 | +`ng-repeat` gets this a lot. |
| 127 | +People try to use jQuery (see above) to add more elements to some container as they're fetched from the server. |
| 128 | +No, bad dog. |
| 129 | +This is what `ng-repeat` is for, and it does its job very well. |
| 130 | +Store the data from the server in an array on your `$scope`, and bind it to the DOM with `ng-repeat`. |
| 131 | + |
| 132 | +**ng-show** |
| 133 | + |
| 134 | +`ng-show` gets this frequently too. |
| 135 | +Conditionally showing and hiding things using jQuery is a common pattern in other apps, but Angular has a better way. |
| 136 | +`ng-show` (and `ng-hide`) conditionally show and hide elements based on boolean expressions. |
| 137 | +Describe the conditions for showing and hiding an element in terms of `$scope` variables: |
| 138 | + |
| 139 | + <div ng-show="!loggedIn">Click <a href="#/login">here</a> to log in</div> |
| 140 | + |
| 141 | +Note also the counterpart `ng-hide` and similar `ng-disabled`. |
| 142 | +Note especially the powerful `ng-switch` that should be used instead of several mutually exclusive `ng-show`s. |
| 143 | + |
| 144 | +**ng-class** |
| 145 | + |
| 146 | +`ng-class` is the last of the big three. |
| 147 | +Conditionally applying classes to elements is another thing commonly done manually using jQuery. |
| 148 | +Angular, of course, has a better way. |
| 149 | +You can give `ng-class` a whitespace-separated set of class names, and then it's identical to ordinary `class`. |
| 150 | +That's not very exciting, so there's a second syntax: |
| 151 | + |
| 152 | + <div ng-class="{ errorClass: isError, warningClass: isWarning, okClass: !isError && !isWarning }">...</div> |
| 153 | + |
| 154 | +Where you give `ng-class` an object, whose keys are CSS class names and whose values are conditional expressions using `$scope` variables. |
| 155 | +The element will then have all the classes whose conditions are truthy, and none of those whose conditions are falsy. |
| 156 | + |
| 157 | +Note also the handy `ng-class-even` and `ng-class-odd`, and the related though somewhat different `ng-style`. |
| 158 | + |
| 159 | + |
| 160 | +### `$watch` and `$apply` |
| 161 | + |
| 162 | +Angular's two-way data binding is the root of all awesome in Angular. |
| 163 | +However, it's not magic, and there are some situations where you need to give it a nudge in the right direction. |
| 164 | + |
| 165 | +When you bind a value to an element in Angular using `ng-model`, `ng-repeat`, etc., Angular creates a `$watch` on that value. |
| 166 | +Then whenever a value on a scope changes, all `$watch`es observing that element are executed, and everything updates. |
| 167 | + |
| 168 | +Sometimes, usually when you're writing a custom directive, you will have to define your own `$watch` on a scope value to make the directive react to changes. |
| 169 | + |
| 170 | +On the flip side, sometimes you change a scope value in some code but the app doesn't react to it. |
| 171 | +Angular checks for scope variable changes after pieces of your code have finished running; for example, when `ng-click` calls a function on your scope, Angular will check for changes and react. |
| 172 | +However, some code is outside of Angular and you'll have to call `scope.$apply()` yourself to trigger the update. |
| 173 | +This is most commonly seen in event handlers in custom directives. |
| 174 | + |
| 175 | +### Combining `ng-repeat` with other directives |
| 176 | + |
| 177 | +`ng-repeat` is extremely useful, one of the most powerful directives in Angular. |
| 178 | +However the transformation it applies to the DOM is substantial. |
| 179 | +Therefore applying other directives (such as `ng-show`, `ng-controller` and others) to the same element as `ng-repeat` generally leads to problems. |
| 180 | + |
| 181 | +If you want to apply a directive to the whole repeat, wrap the repeat in a parent element and put it there. |
| 182 | +If you want to apply a directive to each inner piece of the repeat, put it on a child of the element with `ng-repeat`. |
| 183 | + |
| 184 | +### `$rootScope` exists, but it can be used for evil |
| 185 | + |
| 186 | +Scopes in Angular form a hierarchy, prototypically inheriting from a root scope at the top of the tree. |
| 187 | +Usually this can be ignored, since most views have a controller, and therefore a scope, of their own. |
| 188 | + |
| 189 | +Occasionally there are pieces of data that you want to make global to the whole app. |
| 190 | +For these, you can inject `$rootScope` and set values on it like any other scope. |
| 191 | +Since the scopes inherit from the root scope, these values will be available to the expressions attached to directives like `ng-show` just like values on your local `$scope`. |
| 192 | + |
| 193 | +Of course, global state sucks and you should use `$rootScope` sparingly, like you would (hopefully) use with global variables in any language. |
| 194 | +In particular, don't use it for code, only data. |
| 195 | +If you're tempted to put a function on `$rootScope`, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested. |
| 196 | + |
| 197 | +Conversely, don't create a service whose only purpose in life is to store and return bits of data. |
0 commit comments