Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit f4517b5

Browse files
bshepherdsonmhevery
authored andcommitted
doc(faq): Add Common Pitfalls section
Describes several common pitfalls new users of Angular fall into that I've observed in #angularjs.
1 parent f54edbb commit f4517b5

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

docs/content/misc/faq.ngdoc

+99
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#FAQ
66

7+
## Questions
8+
79
### Why is this project called "AngularJS"? Why is the namespace called "ng"?
810

911
Because HTML has Angular brackets and "ng" sounds like "Angular".
@@ -96,3 +98,100 @@ AJAX Apps}".
9698
### How is Angular licensed?
9799

98100
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

Comments
 (0)