After two years of development Angular 2.0 Final has been officially released on September 14, 2016. In this blog I’ll describe how to create your first Angular 2 project.
During the last couple of months Angular 2 was substantially redesigned/improved in several areas.
Now the app consists of modules, where one is a bootable module that identifies the root component of your app and declares other modules, components, directive, pipes, providers, and routes that are used in this module. Now there is no need to repeat these artifacts in every component. A module is a class decorated with the @NgModule() annotation, and you declare all these artifacts there. For example, the bootable module of your app may look like this:
import { NgModule } from '@angular/core'; import { LocationStrategy, HashLocationStrategy } from '@angular/common'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; import { RouterModule } from '@angular/router'; // other import statements are omitted for brevity @NgModule({ imports: [ BrowserModule, FormsModule, ReactiveFormsModule, RouterModule.forRoot([ {path: '', component: HomeComponent}, {path: 'products/:productId', component: ProductDetailComponent} ]) ], declarations: [ ApplicationComponent, CarouselComponent, FooterComponent, HomeComponent, NavbarComponent, ProductDetailComponent, ProductItemComponent, SearchComponent, StarsComponent ], providers: [ { provide: LocationStrategy, useClass: HashLocationStrategy }, ProductService ], bootstrap: [ ApplicationComponent ] }) export class AppModule {}
Only the bootable module can be BrowserModule. If your app uses several module (e.g. ShipmentModule, BillingModule, FormsModule, HttpModule), those modules are called feature modules are based on the CommonModule instead of the BrowserModule. Each of the feature modules can be loaded either eagerly when the app starts, or lazily, e.g. when the user clicks on the Shipping link.
The code of your app can be compiled either dynamically or statically. If it’s dynamically compiled in the browser, this is called just-in-time compilation (JIT). If the code is precompiled, it’s called ahead-of-time (AoT) compilation. I’m talking about the Angular compiler-cli (ngc), and not just transpiling from TypeScript to JavaScript here. A half of the size of a small app is the angular compiler itself, and just by using the AoT you’re app becomes slimmer because the compiler won’t be downloaded to the browser. One of the reasons the modules were introduced is that it helps the Angular compiler to know which artifacts has to be compiled for the module.
In this blog we’ll use the JIT compilation, and I’ll show you how to start a new Angular 2 project (managed by npm) from scratch without using the scaffolding tool Angular-CLI.
To start a new project, create a new directory (e.g. angular-seed) and open it in the command window. Then run the command npm init -y, which will create the initial version of the package.json configuration file. Normally npm init asks several questions while creating the file, but the -y flag makes it accept the default values for all options. The following example shows the log of this command running in the empty angular-seed directory.
$ npm init -y Wrote to /Users/username/angular-seed/package.json: { "name": "angular-seed", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
Most of the generated configuration is needed either for publishing the project into the npm registry or while installing the package as a dependency for another project.
Because we’re not going to publish our app into the npm registry, you should remove all of the properties except name, description, and scripts. The configuration of any npm-based project is located in the file package.json, which can look like this:
{ "name": "angular-seed", "description": "A simple npm-managed project", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" } }
The scripts configuration allows you to specify commands that you can run in the command window. By default, npm init creates the test command, which can be run like this: npm test. Let’s replace it with the start command that we’ll be using for launching a web server that will feed our app to the browser. Several simple Web servers are available, and we’ll be using the one called live-server that’s we’ll add to the generated package.json a bit later. Here’s the configuration of the scripts property:
{ ... "scripts": { "start": "live-server" } }
While the start command is one of the pre-defined commands in npm scripts, and you can run it from the command window by entering npm start. Actually, you can define and run any other command that would serve as a shortcut for any command you could run manually, but in this case you’d need to run such command as follows: npm run mycommand.
Now we want npm to download Angular to this project as a dependency. We want Angular with its dependencies to be downloaded to our project directory node-modules. We also want local versions of SystemJS, live-server, the TypeScript compiler, and any other third-party libraries that our app needs.
So let’s add the dependencies and devDependencies sections to the package.json file so it’ll include everything that a typical Angular 2 app needs:
{ "name": "angular-seed", "description": "My simple project", "private": true, "scripts": { "start": "live-server" }, "dependencies": { "@angular/common": "2.0.0", "@angular/compiler": "2.0.0", "@angular/core": "2.0.0", "@angular/forms": "2.0.0", "@angular/http": "2.0.0", "@angular/platform-browser": "2.0.0", "@angular/platform-browser-dynamic": "2.0.0", "@angular/router": "3.0.0", "core-js": "^2.4.0", "rxjs": "5.0.0-beta.12", "systemjs": "0.19.37", "zone.js": "0.6.21" }, "devDependencies": { "live-server": "0.8.2", "typescript": "^2.0.0" } }
Now run the command npm install on the command line from the directory where your package.json is located, and npm will download the preceding packages and their dependencies into the node_modules folder. After this process is complete, you’ll see a couple of hundred (sigh) of directories and subdirectories subdirectories in the node_modules dir, including @angular, systemjs, live-server, and typescript.
angular-seed
├── index.html
├── package.json
└── app
└── app.ts
├──node_modules
├── @angular
├── systemjs
├── typescript
├── live-server
└── …
In the angular-seed folder, let’s create a slightly modified version of index.html with the following content:
<!DOCTYPE html> <html> <head> <title>Angular seed project</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="node_modules/typescript/lib/typescript.js"></script> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('app').catch(function(err){ console.error(err); }); </script> </head> <body> <app>Loading...</app> </body> </html>
The script tags load the required dependencies of Angular from the local directory node_modules. Angular modules will be loaded according to the SystemJS configuration file systemjs.config.js, which can look as follows:
System.config({ transpiler: 'typescript', typescriptOptions: {emitDecoratorMetadata: true}, map: { '@angular': 'node_modules/@angular', 'rxjs' : 'node_modules/rxjs' }, paths: { 'node_modules/@angular/*': 'node_modules/@angular/*/bundles' }, meta: { '@angular/*': {'format': 'cjs'} }, packages: { 'app' : {main: 'main', defaultExtension: 'ts'}, 'rxjs' : {main: 'Rx'}, '@angular/core' : {main: 'core.umd.min.js'}, '@angular/common' : {main: 'common.umd.min.js'}, '@angular/compiler' : {main: 'compiler.umd.min.js'}, '@angular/platform-browser' : {main: 'platform-browser.umd.min.js'}, '@angular/platform-browser-dynamic': {main: 'platform-browser-dynamic.umd.min.js'} } });
The app code will consist of three files:
– app.component.ts – the one and only component of our app
– app.module.ts – The declaration of the module that will include our component
– main.ts – the bootstrap of the module
Let’s create the file app.component.ts with the following content:
---- import {Component} from '@angular/core'; @Component({ selector: 'app', template: `<h1>Hello {{ name }}!</h1>` }) export class AppComponent { name: string; constructor() { this.name = 'Angular 2'; } }
Now you need to create a module that will contain our AppComponent. This code we’ll place inside the app.module.ts file:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
This file just contains the definition of the Angular module. The class is annotated with @NgModule that includes the BrowserModule that every browser must import. Since our module contains only one class, we need to list it in the declarations property, and list it as the bootstrap class.
In the section packages of the SystemJS config file we mapped the name app to main.ts that will look like this:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);
The last line of the above script actually compiles and loads the module.
Start the application by executing the npm start command from the angular-seed directory, and it’ll open your browser and show the message “Loading…” for a second, followed by “Hello Angular 2!”.
You can find the source code of our angular-seed project at https://github.com/Farata/angular2typescript/tree/master/chapter2/angular-seed.
Thanks for the tutorial !
There is a lot of breaking changes in recent angular RC and it s really confusing.
I started a project with rc1 , I have to make changes for RC5, and now some things are broken again with RC6. I m seriously wondering to move to aurelia.io for my next project. Angular2 seems an over-engineered project with too much complexity for nothing. Maybe I will change my mind, but the first week with angular2 does not convinced me 😉
If you’re looking for a simple solution for a small project, Angular 2 may be not for you. But if you need a complete solution, go Angular 2.
The upgrade from RC5 to RC6 didn’t require any changes in my apps – just the package.json and systemjs config files were affected.
OMG, angular 2 is in RC now, not GA. some breaking changes are predictable. this is completely normal.
by the way, my Material2 app (started with RC.5) is broken now (after RC.6 upgrade) but that was my choice to use smth in alpha stage.
Don’t panic 😉 Angular 2 with that new NgModel lazy architecture is really awesome, and i’m not sure that i’ll move to some other framework at all.
regards
> OMG, angular 2 is in RC now, not GA. some breaking changes are predictable
No. And because the guys know that, they commited themselves to semantic versioning:
https://www.infoq.com/news/2016/09/angular-2-final-released
MANY thanks Yakov – What a moving target this has been!
Tell me about it 🙂
where is import { Control } from ‘@angular/common’ in rc5 and now gone in rc6
RC.6 removes deprecated API
import { ReactiveFormsModule, FormControl, FormGroup } from ‘@angular/forms’;
the script is like this in rc5 when i upgraded to rc6 “import Control” cannot be found!
import { Control } from ‘@angular/common’;
export class BasicValidators{
static email(control: Control){
var regEx = /^(([^()\[\]\\.,;:\s@”]+(\.[^()\[\]\\.,;:\s@”]+)*)|(“.+”))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var valid = regEx.test(control.value);
I really liked the post on stability of Angular2 and its drastic changes. Your posts are more informative looking forward to hear many such from you 🙂 . Keep going.
Is there any reason to use JIT now that the AOT is out??
How install the angular-cli to generate project with Angular RC6 ?|
npm install -g angular-cli@webpack
Thank you for your helper,
I installed npm install -g angular-cli@webpack ,
but still in my packge.json this Angular RC5. I’d want to create new projects with angular-cli using AngularRC6.
Any idea?
Looks like they still didn’t fix this issue: https://github.com/angular/angular-cli/issues/1968
There is a hack with downgrading webpack to beta 19, but you better wait for the next release of CLI
Thank’s a lot!
Actually, after the Final release you can just run npm install -g angular-cli
Then enter ng –version, and you should see beta.14 that supports webpack.
how can i upload file using reactive form in this angular 2.0.0 version.
i try to do but input type=file returns null instead of file name.
my code is here,
teaminfo.ts :-
—————–
import { Component, Inject } from ‘@angular/core’;
import { Router, ActivatedRoute } from ‘@angular/router’;
import { ReactiveFormsModule, FormGroup, FormArray, FormBuilder, Validators } from ‘@angular/forms’;
@Component({
selector: ‘team-info’,
templateUrl: ‘./servicer/registration/templates/team-info.html’
})
export class TeamInfoComponent {
teamForm: FormGroup;
servicer = new ServicerModel();
constructor(
fb: FormBuilder,
private _router: Router,
private _route: ActivatedRoute
) {
this.teamForm = fb.group({
teamfilename: [”],
});
}
onSubmit(value: any) {
console.log(value);
}
}
team-info.html:-
—————-
Upload Photo
Next
HI! Thanks for the article… my domain is done in Angular2! http://davidmartinezros.com You can see some examples and projects did in Angular2 and news projects will. Come and take a look!!!