One framework.
Mobile and desktop.

Fast

Angular computes updates based on changes to data, not DOM, for fast updates that scale to the largest data sets with minimal memory overhead.

Mobile

With Angular Universal for server-side rendering and Web Workers for smooth scrolling and transitions, Angular 2 solves the core challenges in mobile web performance.

Flexible

Supports several languages including plain JavaScript, TypeScript, and Dart. Also supports both object-style data structure with POJO data-binding and functional reactive style with unidirectional data flow and support for observables and immutable data structures.


The Basics

In Angular you display data by defining components. Data in your component classes is automatically available to display in your templates or control how they render as in the example below.

While this example uses TypeScript, Angular works equally well with ES5, ES6 and Dart as well.

Try in Plunker

<label>Name:</label> <!-- data-bind to the input element; store value in yourName --> <input type="text" [(ngModel)]="yourName" placeholder="Enter a name here"> <hr> <!-- conditionally display `yourName` --> <h1 [hidden]="!yourName">Hello {{yourName}}!</h1> import {Component} from 'angular2/core'; @Component({ // Declare the tag name in index.html to where the component attaches selector: 'hello-world', // Location of the template for this component templateUrl: 'src/hello_world.html' }) export class HelloWorld { // Declaring the variable for binding with initial value yourName: string = ''; } <!DOCTYPE html> <html> <head> <title>Angular 2 QuickStart</title> <!-- 1. Load libraries --> <script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script> <script src="https://code.angularjs.org/tools/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.dev.js"></script> <!-- 2. Configure SystemJS --> <script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, packages: {'src': {defaultExtension: 'ts'}} }); </script> <!-- 3. Bootstrap --> <script> System.import('angular2/platform/browser').then(function(ng){ System.import('src/hello_world').then(function(src) { ng.bootstrap(src.HelloWorld); }); }); </script> </head> <!-- 4. Display the application --> <body> <hello-world>Loading...</hello-world> </body> </html>

Structuring Apps With Components

Groups of coordinated components divide the responsibilities of our application. This ToDo list app has a separate component for the form, the list, and the core app logic. Where the previous example component referenced templates in separate files, this one shows using inline templates.

Defining types as we do here in Todo.ts communicates our intention to other developers, helps us find bugs in our code, and lets IDEs do more work for us in refactoring, code navigation, and code completion.

Try in Plunker

import {Component} from 'angular2/core'; import {Todo} from './todo'; import {TodoList} from './todo_list'; import {TodoForm} from './todo_form'; @Component({ selector: 'todo', template: ` <h2>Todo</h2> <span>{{remaining}} of {{todos.length}} remaining</span> [ <a href="javascript: false" (click)="archive()">archive</a> ] <todo-list [todos]="todos"></todo-list> <todo-form (newTask)="addTask($event)"></todo-form>`, directives: [TodoList, TodoForm] }) export class TodoApp { todos: Todo[] = [ {text:'learn angular', done:true}, {text:'build an angular app', done:false} ]; get remaining(): number { return this.todos.reduce((count, todo: Todo) => count + todo.done, 0); } archive(): void { var oldTodos = this.todos; this.todos = []; oldTodos.forEach((todo: Todo) => { if (!todo.done) this.todos.push(todo); }); } addTask(task: Todo) { this.todos.push(task); } } import {Component, Output, EventEmitter} from 'angular2/core'; import {Todo} from './todo'; @Component({ selector: 'todo-form', template: ` <form (ngSubmit)="addTodo()"> <input type="text" [(ngModel)]="task" size="30" placeholder="add new todo here"> <input class="btn-primary" type="submit" value="add"> </form>` }) export class TodoForm { @Output() newTask = new EventEmitter<Todo>(); task: string = ''; addTodo() { if (this.task) { this.newTask.next({text:this.task, done:false}); } this.task = ''; } } import {Component, Input} from 'angular2/core'; import {Todo} from './todo'; @Component({ selector: 'todo-list', styles: [` .done-true { text-decoration: line-through; color: grey; }` ], template: ` <ul class="unstyled"> <li *ngFor="var todo of todos"> <input type="checkbox" [(ngModel)]="todo.done"> <span class="done-{{todo.done}}">{{todo.text}}</span> </li> </ul>` }) export class TodoList { @Input() todos: Todo[]; } // Declare an interaface for type safety export interface Todo { text: string, done: boolean } <!DOCTYPE html> <html> <head> <title>Angular 2 QuickStart</title> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <!-- 1. Load libraries --> <script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script> <script src="https://code.angularjs.org/tools/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.dev.js"></script> <!-- 2. Configure SystemJS --> <script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, packages: {'src': {defaultExtension: 'ts'}} }); </script> <!-- 3. Bootstrap --> <script> System.import('angular2/platform/browser').then(function(ng){ System.import('src/todo_app').then(function(src) { ng.bootstrap(src.TodoApp); }); }); </script> </head> <!-- 4. Display the application --> <body> <todo class="container" style="display: block">Loading...</todo> </body> </html>

Advanced Component Communication

This demo shows an efficient implementation of tabs/panes. Each pane is only instantiated while it is visible. Panes which are not visible are released and do not have associated memory, DOM and change detection cost.

The demo also showcases dependency injection and the ability of one component to query for other components. Such queries automatically update even as detail panes are added. This allows the tabs component to work with ngFor without any special knowledge of it.

Try in Plunker

import {Component} from 'angular2/core'; import {UiTabs, UiPane} from './ui_tabs'; @Component({ selector: 'di-demo', template: ` <h4>Tabs Demo</h4> <ui-tabs> <template ui-pane title='Overview' active="true"> You have {{details.length}} details. </template> <template *ngFor="#detail of details" ui-pane [title]="detail.title"> {{detail.text}} <br><br> <button class="btn" (click)="removeDetail(detail)">Remove</button> </template> <template ui-pane title='Summary'> Next last ID is {{id}}. </template> </ui-tabs> <hr> <button class="btn" (click)="addDetail()">Add Detail</button> `, directives: [UiTabs, UiPane] }) export class DiDemo { details: Detail[] = []; id: number = 0; addDetail() { this.id++; this.details.push({ title: `Detail ${this.id}`, text: `Some detail text for ${this.id}...` }); } removeDetail(detail) { this.details = this.details.filter((d) => d !== detail); } } import {Component, Directive, Input, QueryList, ViewContainerRef, TemplateRef, ContentChildren} from 'angular2/core'; @Directive({ selector: '[ui-pane]' }) export class UiPane { @Input() title: string; private _active:boolean = false; constructor(public viewContainer: ViewContainerRef, public templateRef: TemplateRef) { } @Input() set active(active: boolean) { if (active == this._active) return; this._active = active; if (active) { this.viewContainer.createEmbeddedView(this.templateRef); } else { this.viewContainer.remove(0); } } get active(): boolean { return this._active; } } @Component({ selector: 'ui-tabs', template: ` <ul class="nav nav-tabs"> <li *ngFor="var pane of panes" (click)="select(pane)" role="presentation" [class.active]="pane.active"> <a href="javascript: false">{{pane.title}}</a> </li> </ul> <ng-content></ng-content> ` }) export class UiTabs { @ContentChildren(UiPane) panes: QueryList<UiPane>; select(pane: UiPane) { this.panes.toArray().forEach((p: UiPane) => p.active = p == pane); } } <!DOCTYPE html> <html> <head> <title>Angular 2 QuickStart</title> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <!-- 1. Load libraries --> <script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script> <script src="https://code.angularjs.org/tools/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.dev.js"></script> <!-- 2. Configure SystemJS --> <script> System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, packages: {'src': {defaultExtension: 'ts'}} }); </script> <!-- 3. Bootstrap --> <script> System.import('angular2/platform/browser').then(function(ng){ System.import('src/di_demo').then(function(src) { ng.bootstrap(src.DiDemo); }); }); </script> </head> <!-- 4. Display the application --> <body> <di-demo class="container" style="display: block;">Loading...</di-demo> </body> </html>