Improve this Doc

FAQ

Questions

Why is this project called "AngularJS"? Why is the namespace called "ng"?

Because HTML has angular brackets and "ng" sounds like "AngularJS".

Is AngularJS a library, framework, plugin or a browser extension?

AngularJS fits the definition of a framework the best, even though it's much more lightweight than a typical framework and that's why many confuse it with a library.

AngularJS is 100% JavaScript, 100% client-side and compatible with both desktop and mobile browsers. So it's definitely not a plugin or some other native browser extension.

What is the AngularJS versioning strategy?

In AngularJS we do not allow intentional breaking changes to appear in versions where only the "patch" number changes. For example between 1.3.12 and 1.3.13 there can be no breaking changes. We do allow breaking changes happen between "minor" number changes. For example between 1.3.15 and 1.4.0 there are a number of breaking changes. That means AngularJS does not follow semantic versioning (semver) where breaking changes are only allowed when the "major" version changes.

We also allow breaking changes between beta releases of AngularJS. For example between 1.4.0-beta.4 and 1.4.0-beta.5 there may be breaking changes. We try hard to minimize these kinds of change only to those where there is a strong use case such as a strongly requested feature improvement, a considerable simplification of the code, a measurable performance improvement, or a better developer experience (especially with regard to upgrading to Angular).

When we are making a release we generate updates to the changelog directly from the commits. This generated update contains a highlighted section that contains all the breaking changes that have been extracted from the commits. We can quickly see in the new changelog exactly what commits contain breaking changes and so can application developers when they are deciding whether to update to a new version of AngularJS.

Features with non-breaking changes can also appear in the "patch" version, e.g. in version 1.6.3 there might be a feature that is not available in 1.6.2.

Finally, deprecation of features might also appear in "minor" version updates. That means the features will still work in this version, but sometimes must be activated specifically.

When are deprecated features removed from the library?

Most of the time we remove a deprecated feature in a next minor version bump. For example, the preAssignBindingsEnabled $compileProvider method was defined in AngularJS 1.5.10, deprecated in 1.6 and will be removed in 1.7.

In case of jqLite we apply a different strategy - we deprecate features that have an equivalent in jQuery that is also deprecated but we only remove the feature once it's removed from jQuery to improve compatibility between jqLite and jQuery. One such example is the bind method, deprecated in favor of on but unlikely to be removed from jqLite any time soon.

What is the version compatibility between AngularJS main and optional modules?

AngularJS code is separated into a main module ("angular"), and a few different optional modules ("angular-animate", "angular-route" etc) that are dependant on the main module. When a new AngularJS version is released, all modules are updated to the new version. This means that the main module and the optional modules must always have the exact same version, down to the patch number, otherwise your application might break.

Therefore you must always explicitly lock down your dependencies, for example in the package.json, the following means that "angular" and "angular-animate" are always updated to the same version:

{
  "angular": "~1.6.0",
  "angular-animate": "~1.6.0"
}

If you define exact versions, make sure core and optional modules are the same:

{
  "angular": "1.6.3",
  "angular-animate": "1.6.3"
}

How does AngularJS ensure code quality and guard against regressions?

When adding new code to AngularJS, we have a very stringent commit policy:

The AngularJS code base has a very large set of unit tests and end-to-end tests. This means that a breaking change will require one or more tests to be changed to allow the tests to pass. So when a commit includes tests that are being removed or modified, this is a flag that the code might include a breaking change. When reviewing the commit we can then decide whether there really is a breaking change and if it is appropriate for the branch to which it is being merged. If so, then we require that the commit message contains an appropriate breaking change message.

Additionally, commits are periodically synced to Google where we test it against applications using the test suites of these applications. This allows us to catch regressions quickly before a release. We've had a pretty good experience with this setup. Only bugs that affect features not used at Google or without sufficient test coverage, have a chance of making it through.

Is AngularJS a templating system?

At the highest level, AngularJS does look like just another templating system. But there is one important reason why the AngularJS templating system is different, that makes it very good fit for application development: bidirectional data binding. The template is compiled in the browser and the compilation step produces a live view. This means you, the developers, don't need to write code to constantly sync the view with the model and the model with the view as in other templating systems.

Do I need to worry about security holes in AngularJS?

Like any other technology, AngularJS is not impervious to attack. AngularJS does, however, provide built-in protection from basic security holes, including cross-site scripting and HTML injection attacks. AngularJS does round-trip escaping on all strings for you and even offers XSRF protection for server-side communication.

AngularJS was designed to be compatible with other security measures like Content Security Policy (CSP), HTTPS (SSL/TLS) and server-side authentication and authorization that greatly reduce the possible attack vectors and we highly recommend their use.

Please read Security for more detailed information about securing AngularJS apps.

Can I download the source, build, and host the AngularJS environment locally?

Yes. See instructions in Downloading.

What browsers does AngularJS work with?

We run our extensive test suite against the following browsers: the latest versions of Chrome, Firefox, Safari, and Safari for iOS, as well as Internet Explorer versions 9-11. See Internet Explorer Compatibility for more details on supporting legacy IE browsers.

If a browser is untested, it doesn't mean it won't work. You can also expect browsers to work that share a large part of their codebase with a browser we test, such as Opera 15 or newer (uses the Blink engine), or the various Firefox derivatives.

What's AngularJS's performance like?

The startup time heavily depends on your network connection, state of the cache, browser used and available hardware, but typically we measure bootstrap time in tens or hundreds of milliseconds.

The runtime performance will vary depending on the number and complexity of bindings on the page as well as the speed of your backend (for apps that fetch data from the backend). For an illustration, we typically build snappy apps with hundreds or thousands of active bindings.

How big is the angular.js file that I need to include?

The size of the file is ~50KB compressed and minified.

Can I use the open-source Closure Library with AngularJS?

Yes, you can use widgets from the Closure Library in AngularJS.

Does AngularJS use the jQuery library?

Yes, AngularJS can use jQuery if it's present in your app when the application is being bootstrapped. If jQuery is not present in your script path, AngularJS falls back to its own implementation of the subset of jQuery that we call jQLite.

For AngularJS 1.8 we support jQuery 2.1+ but we suggest jQuery 3.5.1 or above to avoid a potential security issue. Earlier versions of jQuery might work correctly with AngularJS but we don't guarantee that.

What is testability like in AngularJS?

Very testable and designed this way from the ground up. It has an integrated dependency injection framework, provides mocks for many heavy dependencies (server-side communication). See ngMock for details.

How can I learn more about AngularJS?

Watch the July 17, 2012 talk "AngularJS Intro + Dependency Injection".

How is AngularJS licensed?

The MIT License.

Can I download and use the AngularJS logo artwork?

Yes! You can find design files in our github repository, under "angular.js/images/logo" The logo design is licensed under a "Creative Commons Attribution-ShareAlike 3.0 Unported License". If you have some other use in mind, contact us.

How can I get some AngularJS schwag?

We often bring a few t-shirts and stickers to events where we're presenting. If you want to order your own, the folks who make our schwag will be happy to do a custom run for you, based on our existing template. By using the design they have on file, they'll waive the setup costs, and you can order any quantity you need.

Stickers For orders of 250 stickers or more within Canada or the United States, contact Tom Witting (or anyone in sales) via email at tom@stickergiant.com, and tell him you want to order some AngularJS stickers just like the ones in job #42711. You'll have to give them your own info for billing and shipping.

As long as the design stays exactly the same, StickerGiant will give you a reorder discount.

For a smaller order, or for other countries, we suggest downloading the logo artwork and making your own.

Common Pitfalls

The AngularJS support channel (#angularjs on Freenode) sees a number of recurring pitfalls that new users of AngularJS fall into. This document aims to point them out before you discover them the hard way.

DOM Manipulation

Stop trying to use jQuery to modify the DOM in controllers. Really. That includes adding elements, removing elements, retrieving their contents, showing and hiding them. Use built-in directives, or write your own where necessary, to do your DOM manipulation. See below about duplicating functionality.

If you're struggling to break the habit, consider removing jQuery from your app. Really. AngularJS has the $http service and powerful directives that make it almost always unnecessary. AngularJS's bundled jQLite has a handful of the features most commonly used in writing AngularJS directives, especially binding to events.

Trying to duplicate functionality that already exists

There's a good chance that your app isn't the first to require certain functionality. There are a few pieces of AngularJS that are particularly likely to be reimplemented out of old habits.

ng-repeat

ng-repeat gets this a lot. People try to use jQuery (see above) to add more elements to some container as they're fetched from the server. No, bad dog. This is what ng-repeat is for, and it does its job very well. Store the data from the server in an array on your $scope, and bind it to the DOM with ng-repeat.

ng-show

ng-show gets this frequently too. Conditionally showing and hiding things using jQuery is a common pattern in other apps, but AngularJS has a better way. ng-show (and ng-hide) conditionally show and hide elements based on boolean expressions. Describe the conditions for showing and hiding an element in terms of $scope variables:

<div ng-show="!loggedIn"><a href="#/login">Click here to log in</a></div>

Note also the counterpart ng-hide and similar ng-disabled. Note especially the powerful ng-switch that should be used instead of several mutually exclusive ng-shows.

ng-class

ng-class is the last of the big three. Conditionally applying classes to elements is another thing commonly done manually using jQuery. AngularJS, of course, has a better way. You can give ng-class a whitespace-separated set of class names, and then it's identical to ordinary class. That's not very exciting, so there's a second syntax:

<div ng-class="{ errorClass: isError, warningClass: isWarning, okClass: !isError && !isWarning }">...</div>

Where you give ng-class an object, whose keys are CSS class names and whose values are conditional expressions using $scope variables. The element will then have all the classes whose conditions are truthy, and none of those whose conditions are falsy.

Note also the handy ng-class-even and ng-class-odd, and the related though somewhat different ng-style.

$watch and $apply

AngularJS's two-way data binding is the root of all awesome in AngularJS. However, it's not magic, and there are some situations where you need to give it a nudge in the right direction.

When you bind a value to an element in AngularJS using ng-model, ng-repeat, etc., AngularJS creates a $watch on that value. Then whenever a value on a scope changes, all $watches observing that element are executed, and everything updates.

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.

On the flip side, sometimes you change a scope value in some code, but the app doesn't react to it. AngularJS checks for scope variable changes after pieces of your code have finished running; for example, when ng-click calls a function on your scope, AngularJS will check for changes and react. However, some code is outside of AngularJS and you'll have to call scope.$apply() yourself to trigger the update. This is most commonly seen in event handlers in custom directives.

Combining ng-repeat with other directives

ng-repeat is extremely useful, one of the most powerful directives in AngularJS. However the transformation it applies to the DOM is substantial. Therefore applying other directives (such as ng-show, ng-controller and others) to the same element as ng-repeat generally leads to problems.

If you want to apply a directive to the whole repeat, wrap the repeat in a parent element and put it there. 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.

$rootScope exists, but it can be used for evil

Scopes in AngularJS form a hierarchy, prototypically inheriting from a root scope at the top of the tree. Usually this can be ignored, since most views have a controller, and therefore a scope, of their own.

Occasionally there are pieces of data that you want to make global to the whole app. For these, you can inject $rootScope and set values on it like any other scope. 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.

Of course, global state sucks and you should use $rootScope sparingly, like you would (hopefully) use with global variables in any language. In particular, don't use it for code, only data. 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.

Conversely, don't create a service whose only purpose in life is to store and return bits of data.