1-What is Angular?

Angular is a platform that makes it easy to build applications with the web. Angular combines declarative templates, dependency injection, end to end tooling, and integrated best practices to solve development challenges. Angular empowers developers to build applications that live on the web, mobile, or the desktop



The Angular CLI is a command line interface tool that can create a project, add files, and perform a variety of ongoing development tasks such as testing, bundling, and deployment.

Step 1. Set up the Development Environment

Verify that you are running at least node 6.9.x and npm 3.x.x by running
node -v and npm -v in a terminal/console window. Older versions produce errors, but newer versions are fine. Otherwise, determine java8 by running java -version
Then install the Angular CLI globally.
npm install -g @angular/cli
If having error in running angular example then uninstall and reinstall latest angular-cli
npm uninstall -g angular-cli
npm cache clear
npm install -g angular-cli gulp typescript
npm install -g @angular/cli@latest

Step 2. Create a new project

Open a terminal window.
Generate a new project and skeleton application by running the following commands
ng new my-app

Step 3: Serve the application

Go to the project directory and launch the server
cd my-app 
ng serve --open

The ng serve command launches the server, watches your files, and rebuilds the app as you make changes to those files.
Using the --open (or just -o) option will automatically open your browser on
http://localhost:4200/

Step 4: Edit your first Angular component

The CLI created the first Angular component for you. This is the root component and it is named app-root. You can find it in ./src/app/app.component.ts.
Open the component file and change the title property from Welcome to app!! to Welcome to My First Angular App!!:
src/app/app.component.ts
export class AppComponent {
  title = 'My First Angular App';
}
 
The browser reloads automatically with the revised title. That's nice, but it could look better.
Open src/app/app.component.css and give the component some style.

src/app/app.component.css
h1 {
 color: #369;
 font-family: Arial, Helvetica, sans-serif;
 font-size: 250%;
}

The following are all in src/
FilePurpose
app/app.component.ts
Defines the same AppComponent as the one in the QuickStart playground. It is the root component of what will become a tree of nested components as the application evolves.
app/app.module.ts
Defines AppModule, the root module that tells Angular how to assemble the application. Right now it declares only the AppComponent. Soon there will be more components to declare.
main.ts
Compiles the application with the JIT compiler and bootstraps the application's main module (AppModule) to run in the browser. The JIT compiler is a reasonable choice during the development of most projects and it's the only viable choice for a sample running in a live-codingenvironment like Plunker. You'll learn about alternative compiling and deployment options later in the documentation.
@Component and @View are ways of adding meta-data to the class that Angular will use to find, and load our component into the DOM. For example, selector:'app-root' is the CSS selected that angular will use to locate our component.
Bootstrapping our application by telling Angular which component to use as the root.

2-Heroes app structure

When you're done with this tutorial, the app will look like this live example / download example .


The src folder

Your app lives in the src folder. All Angular components, templates, styles, images, and anything else your app needs go here. Any files outside of this folder are meant to support building your app.

File
Purpose
app/app.component.{ts,html,css,spec.ts}
Defines the AppComponent along with an HTML template, CSS stylesheet, and a unit test. It is the root component of what will become a tree of nested components as the application evolves.
app/app.module.ts
Defines AppModule, the root module that tells Angular how to assemble the application. Right now it declares only the AppComponent. Soon there will be more components to declare.
assets/*
A folder where you can put images and anything else to be copied wholesale when you build your application.
environments/*
This folder contains one file for each of your destination environments, each exporting simple configuration variables to use in your application. The files are replaced on-the-fly when you build your app. You might use a different API endpoint for development than you do for production or maybe different analytics tokens. You might even use some mock services. Either way, the CLI has you covered.
favicon.ico
Every site wants to look good on the bookmark bar. Get started with your very own Angular icon.
index.html
The main HTML page that is served when someone visits your site. Most of the time you'll never need to edit it. The CLI automatically adds all js and css files when building your app so you never need to add any <script> or <link> tags here manually.
main.ts
The main entry point for your app. Compiles the application with the JIT compiler and bootstraps the application's root module (AppModule) to run in the browser. You can also use the AOT compiler without changing any code by passing in --aot to ng build or ng serve.
polyfills.ts
Different browsers have different levels of support of the web standards. Polyfills help normalize those differences. You should be pretty safe with core-js and zone.js, but be sure to check out the Browser Support guide for more information.
styles.css
Your global styles go here. Most of the time you'll want to have local styles in your components for easier maintenance, but styles that affect all of your app need to be in a central place.
test.ts
This is the main entry point for your unit tests. It has some custom configuration that might be unfamiliar, but it's not something you'll need to edit.
tsconfig.{app|spec}.json
TypeScript compiler configuration for the Angular app (tsconfig.app.json) and for the unit tests (tsconfig.spec.json).
The root folder
The src/ folder is just one of the items inside the project's root folder. Other files help you build, test, maintain, document, and deploy the app. These files go in the root folder next to src/.
File
Purpose
e2e/
Inside e2e/ live the end-to-end tests. They shouldn't be inside src/ because e2e tests are really a separate app that just so happens to test your main app. That's also why they have their own tsconfig.e2e.json.
node_modules/
Node.js creates this folder and puts all third party modules listed in package.json inside of it.
.angular-cli.json
Configuration for Angular CLI. In this file you can set several defaults and also configure what files are included when your project is built. Check out the official documentation if you want to know more
.editorconfig
Simple configuration for your editor to make sure everyone that uses your project has the same basic configuration. Most editors support an .editorconfig file. See http://editorconfig.org for more information.
.gitignore
Git configuration to make sure autogenerated files are not commited to source control.
karma.conf.js
Unit test configuration for the Karma test runner, used when running ng test.
package.json
npm configuration listing the third party packages your project uses. You can also add your own custom scripts here.
protractor.conf.js
End-to-end test configuration for Protractor, used when running ng e2e.
README.md
Basic documentation for your project, pre-filled with CLI command information. Make sure to enhance it with project documentation so that anyone checking out the repo can build your app!
tsconfig.json
TypeScript compiler configuration for your IDE to pick up and give you helpful tooling.
tslint.json
Linting configuration for TSLint together with Codelyzer, used when running ng lint. Linting helps keep your code style consistent
  • The Tour of Heroes app uses the double curly braces of interpolation (a type of one-way data binding) to display the app title and properties of a Hero object.
  • You wrote a multi-line template using ES2015's template literals to make the template readable.
  • You added a two-way data binding to the <input> element using the built-in ngModel directive. This binding both displays the hero's name and allows users to change it.
  • The ngModel directive propagates changes to every other binding of the hero.name.
Your app should look like this live example / download example .

In this page, you'll expand the Tour of Heroes app to display a list of heroes, and allow users to select a hero and display the hero's details.


  • The Tour of Heroes app displays a list of selectable heroes.
  • You added the ability to select a hero and show the hero's details.
  • Learned how to use the built-in directives ngIf and ngFor in a component's template.
  • When you're done with this page, the app should look like this live example / download example .
    <li *ngFor="let hero of heroes">

    The (*) prefix to ngFor is a critical part of this syntax. It indicates that the <li> element and its children constitute a master template.

    The ngFor directive iterates over the component's heroes array and renders an instance of this template for each hero in that array.

    The let hero part of the expression identifies hero as the template input variable, which holds the current hero item for each iteration. You can reference this variable within the template to access the current hero's properties.

    Read more about ngFor and template input variables in the Showing an array property with *ngFor section of the Displaying Data page and the ngFor section of the Template Syntax page.

    Learn more about event binding at the User Input page and the Event binding section of the Template Syntax page.
    Read more about ngIf and ngFor in the Structural Directives page and the Built-in directives section of the Template Syntax page.

    5-Multiple Components

    You'll need to break it up into sub-components, each focused on a specific task or workflow. Eventually, the AppComponent could become a simple shell that hosts those sub-components.
    In this page, you'll take the first step in that direction by carving out the hero details into a separate, reusable component. When you're done, the app should look like this live example / download example .
    <hero-detail [hero]="selectedHero"></hero-detail>
    Putting square brackets around the hero property, to the left of the equal sign (=), makes it the target of a property binding expression. You must declare a target binding property to be an input property. Otherwise, Angular rejects the binding and throws an error.
    >>>src/app/hero-detail.component.ts (excerpt)
    export class HeroDetailComponent {
      @Input() hero: Hero;
    }


    What changed?
    As before, whenever a user clicks on a hero name, the hero detail appears below the hero list. But now the HeroDetailView is presenting those details.
    Refactoring the original AppComponent into two components yields benefits, both now and in the future:
    1. You simplified the AppComponent by reducing its responsibilities.
    2. You can evolve the HeroDetailComponent into a rich hero editor without touching the parent AppComponent.
    3. You can evolve the AppComponent without touching the hero detail view.
    4. You can re-use the HeroDetailComponent in the template of some future parent component.

    6-Services
    Instead of copying and pasting the same code over and over, you'll create a single reusable data service and inject it into the components that need it. Using a separate service keeps components lean and focused on supporting the view, and makes it easy to unit-test components with a mock service.
    Because data services are invariably asynchronous, you'll finish the page with a Promise-based version of the data service.
    Here's what you achieved in this page:
    • You created a service class that can be shared by many components.
    • You used the ngOnInit lifecycle hook to get the hero data when the AppComponent activates.
    • You defined the HeroService as a provider for the AppComponent.
    • You created mock hero data and imported them into the service.
    • You designed the service to return a Promise and the component to get the data from the Promise.
    When you're done with this page, the app should look like this live example / download example .

    The naming convention for service files is the service name in lowercase followed by .service. For a multi-word service name, use lower dash-case. For example, the filename for SpecialSuperHeroService is special-super-hero.service.ts.

    Injectable services

    Notice that you imported the Angular Injectable function and applied that function as an @Injectable() decorator.
    Don't forget the parentheses. Omitting them leads to an error that's difficult to diagnose.
    The @Injectable() decorator tells TypeScript to emit metadata about the service. The metadata specifies that Angular may need to inject other dependencies into this service.

    Although the HeroService doesn't have any dependencies at the moment, applying the @Injectable() decorator ​from the start ensures consistency and future-proofing.

    Inject the HeroService

    Instead of using the new line, you'll add two lines.
    • Add a constructor that also defines a private property.
    • Add to the component's providers metadata.
    Add the constructor:
    src/app/app.component.ts (constructor)
    constructor(private heroService: HeroService) { }

    src/app/app.component.ts (providers)
    providers: [HeroService]

    The ngOnInit lifecycle hook

    AppComponent should fetch and display hero data with no issues.
    You might be tempted to call the getHeroes() method in a constructor, but a constructor should not contain complex logic, especially a constructor that calls a server, such as a data access method. The constructor is for simple initializations, like wiring constructor parameters to properties.
    To have Angular call getHeroes(), you can implement the Angular ngOnInit lifecycle hook. Angular offers interfaces for tapping into critical moments in the component lifecycle: at creation, after each change, and at its eventual destruction.
    Each interface has a single method. When the component implements that method, Angular calls it at the appropriate time.

    Read more about lifecycle hooks in the Lifecycle Hooks page.
    export class AppComponent implements OnInit {
      title = 'Tour of Heroes';
      heroes: Hero[];
      selectedHero: Hero;

      constructor(private heroService: HeroService) { }

      ngOnInit(): void {
        // TODO Auto-generated method stub
        this.getHeroes();
      }

      onSelect(hero: Hero): void {
        this.selectedHero = hero;
      }

      getHeroes(): void {
        this.heroService.getHeroes().then(heroes => this.heroes = heroes);
      }
    }

    7-Routing
    There are new requirements for the Tour of Heroes app:
    • Add a Dashboard view.
    • Add the ability to navigate between the Heroes and Dashboard views.
    • When users click a hero name in either view, navigate to a detail view of the selected hero.
    • When users click a deep link in an email, open the detail view for a particular hero.

    When you’re done, users will be able to navigate the app like this live example / download example.



    base href is essential
    For more information, see the Set the base href section of the Routing and Navigation page.
    The route definition has the following parts:
    • Path: The router matches this route's path to the URL in the browser address bar (for example: heroes).
    • Component: The component that the router should create when navigating to this route (HeroesComponent).
    Read more about defining routes with Routes in the Routing & Navigation page.

    The forRoot() method is called because a configured router is provided at the app's root. The forRoot() method supplies the Router service providers and directives needed for routing, and performs the initial navigation based on the current browser URL.

    Router outlet

    If you paste the path, /heroes, into the browser address bar at the end of the URL, the router should match it to the heroes route and display the HeroesComponent. However, you have to tell the router where to display the component. To do this, you can add a <router-outlet> element at the end of the template. RouterOutlet is one of the directives provided by the RouterModule. The router displays each component immediately below the <router-outlet> as users navigate through the app.
    Users shouldn't have to paste a route URL into the address bar. Instead, add an anchor tag to the template that, when clicked, triggers navigation to the HeroesComponent.

    Since the link is not dynamic, a routing instruction is defined with a one-time binding to the route path. Looking back at the route configuration, you can confirm that '/heroes' is the path of the route to the HeroesComponent.
    The browser's address bar shows /. The route path to HeroesComponent is /heroes, not /. Soon you'll add a route that matches the path /.
    Click the Heroes navigation link. The address bar updates to /heroes and the list of heroes displays.
    The AppComponent is now attached to a router and displays routed views. For this reason, and to distinguish it from other kinds of components, this component type is called a router component.

    Add a dashboard

    Routing only makes sense when multiple views exist. To add another view, create a placeholder DashboardComponent, which users can navigate to and from.
    src/app/dashboard.component.ts (v1)

    import { Component } from '@angular/core';

    @Component({
      selector: 'my-dashboard',
      template: '<h3>My Dashboard</h3>'
    })
    export class DashboardComponent { }
    Configure the dashboard route
    To teach app.module.ts to navigate to the dashboard, import the dashboard component and add the following route definition to the Routes array of definitions.
    src/app/app.module.ts (Dashboard route)
    {
      path: 'dashboard',
      component: DashboardComponent
    },

    Add navigation to the template

    Add a dashboard navigation link to the template, just above the Heroes link.
    src/app/app.component.ts (template-v3)

    template: `
       <h1>{{title}}</h1>
       <nav>
         <a routerLink="/dashboard">Dashboard</a>
         <a routerLink="/heroes">Heroes</a>
       </nav>
       <router-outlet></router-outlet>
    The <nav> tags don't do anything yet, but they'll be useful later when you style the links.

    Navigating to hero details

    While the details of a selected hero displays at the bottom of the HeroesComponent, users should be able to navigate to the HeroDetailComponent in the following additional ways:

    • From the dashboard to a selected hero.
    • From the heroes list to a selected hero.
    • From a "deep link" URL pasted into the browser address bar.
    Routing to a hero detail
    You can add the hero's id to the URL. When routing to the hero whose id is 11, you could expect to see a URL such as this:
    /detail/11
    Configure a route with a parameter
    Use the following route definition.
    src/app/app.module.ts (hero detail)
         
    {
      path: 'detail/:id',
      component: HeroDetailComponent
    },

    The colon (:) in the path indicates that :id is a placeholder for a specific hero id when navigating to the HeroDetailComponent.
    Revise the HeroDetailComponent
    import 'rxjs/add/operator/switchMap';
    import { Component, OnInit }        from '@angular/core';
    import { ActivatedRoute, ParamMap } from '@angular/router';
    import { Location }                 from '@angular/common';

    import { Hero }         from './hero';
    import { HeroService }  from './hero.service';

    @Component({
      selector: 'hero-detail',
      templateUrl: './hero-detail.component.html',
    })
    export class HeroDetailComponent implements OnInit {
      hero: Hero;

      constructor(
        private heroService: HeroService,
        private route: ActivatedRoute,
        private location: Location
      ) {}

      ngOnInit(): void {
        this.route.paramMap
          .switchMap((params: ParamMap) => this.heroService.getHero(+params.get('id')))
          .subscribe(hero => this.hero = hero);
      }

      goBack(): void {
        this.location.back();
      }
    }
    The switchMap operator maps the id in the Observable route parameters to a new Observable, the result of the HeroService.getHero() method.
    If a user re-navigates to this component while a getHero request is still processing, switchMap cancels the old request and then calls HeroService.getHero() again.

    The hero id is a number. Route parameters are always strings. So the route parameter value is converted to a number with the JavaScript (+) operator.

    Users have several ways to navigate to the HeroDetailComponent.
    To navigate somewhere else, users can click one of the two links in the AppComponent or click the browser's back button. Now add a third option, a goBack() method that navigates backward one step in the browser's history stack using the Location service you injected previously.
    goBack(): void {
        this.location.back();
      }

    You'll wire this method with an event binding to a Back button that you'll add to the component template.

    <button (click)="goBack()">Back</button>

    Select a dashboard hero

    When a user selects a hero in the dashboard, the app should navigate to the HeroDetailComponent to view and edit the selected hero.
    Although the dashboard heroes are presented as button-like blocks, they should behave like anchor tags. When hovering over a hero block, the target URL should display in the browser status bar and the user should be able to copy the link or open the hero detail view in a new tab.

    To achieve this effect, reopen dashboard.component.html and replace the repeated <div *ngFor...> tags with <a> tags. Change the opening <a> tag to the following:
    <a *ngFor="let hero of heroes"  [routerLink]="['/detail', hero.id]"  class="col-1-4">
    Notice the [routerLink] binding. As described in the Router links section of this page, top-level navigation in the AppComponent template has router links set to fixed paths of the destination routes, "/dashboard" and "/heroes".
    This time, you're binding to an expression containing a link parameters array. The array has two elements: the path of the destination route and a route parameter set to the value of the current hero's id.

    Refactor routes to a Routing Module

    It's a good idea to refactor the routing configuration into its own class. The current RouterModule.forRoot() produces an Angular ModuleWithProviders, a class dedicated to routing should be a routing module. For more information, see the Milestone #2: The Routing Module section of the Routing & Navigation page.
    src/app/app-routing.module.ts
    import { NgModule }             from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';

    import { DashboardComponent }   from './dashboard.component';
    import { HeroesComponent }      from './heroes.component';
    import { HeroDetailComponent }  from './hero-detail.component';

    const routes: Routes = [
      { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
      { path: 'dashboard',  component: DashboardComponent },
      { path: 'detail/:id', component: HeroDetailComponent },
      { path: 'heroes',     component: HeroesComponent }
    ];

    @NgModule({
      imports: [ RouterModule.forRoot(routes) ],
      exports: [ RouterModule ]
    })
    export class AppRoutingModule {}

    The following points are typical of routing modules:
    • The Routing Module pulls the routes into a variable. The variable clarifies the routing module pattern in case you export the module in the future.
    • The Routing Module adds RouterModule.forRoot(routes) to imports.
    • The Routing Module adds RouterModule to exports so that the components in the companion module have access to Router declarables, such as RouterLink and RouterOutlet.
    • There are no declarations. Declarations are the responsibility of the companion module.
    • If you have guard services, the Routing Module adds module providers. (There are none in this example.

    Select a hero in the HeroesComponent

    In the HeroesComponent, the current template exhibits a "master/detail" style with the list of heroes at the top and details of the selected hero below.
    src/app/heroes.component.ts (current template)
       
    template: `
      <h1>{{title}}</h1>
      <h2>My Heroes</h2>
      <ul class="heroes">
        <li *ngFor="let hero of heroes"
          [class.selected]="hero === selectedHero"
          (click)="onSelect(hero)">
          <span class="badge">{{hero.id}}</span> {{hero.name}}
        </li>
      </ul>
      <hero-detail [hero]="selectedHero"></hero-detail>
    `,
    Delete the <h1> at the top.
    Delete the last line of the template with the <hero-detail> tags.
    You'll no longer show the full HeroDetailComponent here. Instead, you'll display the hero detail on its own page and route to it as you did in the dashboard.

    However, when users select a hero from the list, they won't go to the detail page. Instead, they'll see a mini detail on this page and have to click a button to navigate to the full detail page.

    Add the mini detail
    Add the following HTML fragment at the bottom of the template where the <hero-detail> used to be:
    <div *ngIf="selectedHero">
      <h2>
        {{selectedHero.name | uppercase}} is my hero
      </h2>
      <button (click)="gotoDetail()">View Details</button>
    </div>
    Pipes are a good way to format strings, currency amounts, dates and other display data. Angular ships with several pipes and you can write your own.
    Read more about pipes on the Pipes page.

    Move content out of the component file
    You still have to update the component class to support navigation to the HeroDetailComponent when users click the View Details button.
    The component file is big. It's difficult to find the component logic amidst the noise of HTML and CSS.
    Before making any more changes, migrate the template and styles to their own files.
    First, move the template contents from heroes.component.ts into a new heroes.component.html file. Don't copy the backticks. As for heroes.component.ts, you'll come back to it in a minute. Next, move the styles contents into a new heroes.component.css file.

    The two new files should look like this:

    src/app/heroes.component.ts (revised metadata)
    @Component({
      selector: 'my-heroes',
      templateUrl: './heroes.component.html',
      styleUrls: [ './heroes.component.css' ]
    })

    export class HeroesComponent implements OnInit {..}
    The styleUrls property is an array of style file names (with paths). You could list multiple style files from different locations if you needed them.
    src/app/heroes.component.ts (gotoDetail)
    gotoDetail(): void {
      this.router.navigate(['/detail', this.selectedHero.id]);
    }
    Note that you're passing a two-element link parameters array—a path and the route parameter—to the router navigate() method, just as you did in the [routerLink] binding back in the DashboardComponent

    Refesh the browser, and here are resuls:

    Summary
    Here's what you achieved in this page:
    • You added the Angular router to navigate among different components.
    • You learned how to create router links to represent navigation menu items.
    • You used router link parameters to navigate to the details of the user-selected hero.
    • You shared the HeroService among multiple components.
    • You moved HTML and CSS out of the component file and into their own files.
    • You added the uppercase pipe to format data.

    8-HTTP
    In this page, you'll make the following improvements.
    • Get the hero data from a server.
    • Let users add, edit, and delete hero names.
    • Save the changes to the server.
    You'll teach the app to make corresponding HTTP calls to a remote server's web API.

    When you're done with this page, the app should look like this live example / download example .

    Providing HTTP Services

    The HttpModule is not a core NgModule. HttpModule is Angular's optional approach to web access. It exists as a separate add-on module called @angular/http and is shipped in a separate script file as part of the Angular npm package.
    You're ready to import from @angular/http because systemjs.config configured SystemJS to load that library when you need it.

    Register for HTTP services

    The app will depend on the Angular http service, which itself depends on other supporting services. The HttpModule from the @angular/http library holds providers for a complete set of HTTP services.

    To allow access to these services from anywhere in the app, add HttpModule to the imports list of the AppModule.
    import { HttpModule } from '@angular/http';


    Notice that you also supply HttpModule as part of the imports array in root NgModule AppModule.

    Simulate the web API

    We recommend registering app-wide services in the root AppModule providers.
    Until you have a web server that can handle requests for hero data, the HTTP client will fetch and save data from a mock service, the in-memory web API.

    Update src/app/app.module.ts with this version, which uses the mock service:
    // Imports for loading & configuring the in-memory web api
    import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
    import { InMemoryDataService }  from './in-memory-data.service';

    if IDE warns about lacking 'angular-in-memory-web-api', you can install it into your system:

    npm install angular-in-memory-web-api --save
    Rather than require a real API server, this example simulates communication with the remote server by adding the InMemoryWebApiModule to the module imports, effectively replacing the Http client's XHR backend service with an in-memory alternative.
    InMemoryWebApiModule.forRoot(InMemoryDataService),

    The forRoot() configuration method takes an InMemoryDataService class that primes the in-memory database. Add the file in-memory-data.service.ts in app with the following content:
    src/app/in-memory-data.service.ts
    import { InMemoryDbService } from 'angular-in-memory-web-api';
    export class InMemoryDataService implements InMemoryDbService {
      createDb() {
        const heroes = [
          { id: 0,  name: 'Zero' },
          { id: 11, name: 'Mr. Nice' },
          { id: 12, name: 'Narco' },
          { id: 13, name: 'Bombasto' },
          { id: 14, name: 'Celeritas' },
          { id: 15, name: 'Magneta' },
          { id: 16, name: 'RubberMan' },
          { id: 17, name: 'Dynama' },
          { id: 18, name: 'Dr IQ' },
          { id: 19, name: 'Magma' },
          { id: 20, name: 'Tornado' }
        ];
        return {heroes};
      }
    }
    This file replaces mock-heroes.ts, which is now safe to delete. Added hero "Zero" to confirm that the data service can handle a hero with id==0.
    The in-memory web API is only useful in the early stages of development and for demonstrations such as this Tour of Heroes. Don't worry about the details of this backend substitution; you can skip it when you have a real web API server.

    Heroes and HTTP

    Now convert getHeroes() to use HTTP.
    src/app/hero.service.ts (updated getHeroes and new class members)
    /**
     * New typescript file
     */
    import { Injectable } from '@angular/core';
    import 'rxjs/add/operator/toPromise';

    import { Hero } from './hero';
    import { Headers, Http } from '@angular/http';

    @Injectable()
    export class HeroService {
        private heroesUrl = 'api/heroes';  // URL to web api

        constructor(private http: Http) { }

        /*
          getHeroes(): Promise<Hero[]> {
            return Promise.resolve(HEROES);
          }
        */
        getHeroes(): Promise<Hero[]> {
          return this.http.get(this.heroesUrl)
                     .toPromise()
                     .then(response => response.json().data as Hero[])
                     .catch(this.handleError);
        }

        private handleError(error: any): Promise<any> {
          console.error('An error occurred', error); // for demo purposes only
          return Promise.reject(error.message || error);
        }

        getHeroesSlowly(): Promise<Hero[]> {
          return new Promise(resolve => {
            // Simulate server latency with 2 second delay
            setTimeout(() => resolve(this.getHeroes()), 2000);
          });
        }

        getHero(id: number): Promise<Hero> {
          return this.getHeroes()
                     .then(heroes => heroes.find(hero => hero.id === id));
        }
    }

    HTTP Promise

    The Angular http.get returns an RxJS Observable. Observables are a powerful way to manage asynchronous data flows. You'll read about Observables later in this page.

    For now, you've converted the Observable to a Promise using the toPromise operator.
    .toPromise()
    The Angular Observable doesn't have a toPromise operator out of the box.
    There are many operators like toPromise that extend Observable with useful capabilities. To use those capabilities, you have to add the operators themselves. That's as easy as importing them from the RxJS library like this:
    import 'rxjs/add/operator/toPromise';

    Extracting the data in the then callback

    In the Promise's then() callback, you call the json method of the HTTP Response to extract the data within the response.
    .then(response => response.json().data as Hero[])
    The response JSON has a single data property, which holds the array of heroes that the caller wants. So you grab that array and return it as the resolved Promise value.
    The caller is unaware that you fetched the heroes from the (mock) server. It receives a Promise of heroes just as it did before.

    Get hero by id

    When the HeroDetailComponent asks the HeroService to fetch a hero, the HeroService currently fetches all heroes and filters for the one with the matching id. That's fine for a simulation, but it's wasteful to ask a real server for all heroes when you only want one. Most web APIs support a get-by-id request in the form api/hero/:id (such as api/hero/11).

    Update the HeroService.getHero() method to make a get-by-id request:
    getHero(id: number): Promise<Hero> {
          const url = `${this.heroesUrl}/${id}`;
          return this.http.get(url)
            .toPromise()
            .then(response => response.json().data as Hero)
            .catch(this.handleError);
        }

    This request is almost the same as getHeroes(). The hero id in the URL identifies which hero the server should update.
    Also, the data in the response is a single hero object rather than an array.

    Add a hero service update() method

    The overall structure of the update() method is similar to that of getHeroes(), but it uses an HTTP put() to persist server-side changes.
    src/app/hero.service.ts (update)
         
    private headers = new Headers({'Content-Type': 'application/json'});

    update(hero: Hero): Promise<Hero> {
      const url = `${this.heroesUrl}/${hero.id}`;
      return this.http
        .put(url, JSON.stringify(hero), {headers: this.headers})
        .toPromise()
        .then(() => hero)
        .catch(this.handleError);

    To identify which hero the server should update, the hero id is encoded in the URL. The put() body is the JSON string encoding of the hero, obtained by calling JSON.stringify. The body content type (application/json) is identified in the request header.
    Refresh the browser, change a hero name, save your change, and click the browser Back button. Changes should now persist.

    Add the ability to add heroes

    To add a hero, the app needs the hero's name. You can use an input element paired with an add button.

    Insert the following into the heroes component HTML, just after the heading:
    src/app/heroes.component.html (add)
         
    <div>
      <label>Hero name:</label> <input #heroName />
      <button (click)="add(heroName.value); heroName.value=''">
        Add
      </button>
    </div>
    In response to a click event, call the component's click handler and then clear the input field so that it's ready for another name.

    src/app/heroes.component.ts (add)
          
    add(name: string): void {
      name = name.trim();
      if (!name) { return; }
      this.heroService.create(name)
        .then(hero => {
          this.heroes.push(hero);
          this.selectedHero = null;
        });
    }
    When the given name is non-blank, the handler delegates creation of the named hero to the hero service, and then adds the new hero to the array.

    Add the ability to delete a hero

    Each hero in the heroes view should have a delete button.

    Add the following button element to the heroes component HTML, after the hero name in the repeated <li> element.
    <button class="delete"
      (click)="delete(hero); $event.stopPropagation()">x</button>
    The <li> element should now look like this:
    src/app/heroes.component.html (li-element)

    <li *ngFor="let hero of heroes" (click)="onSelect(hero)"
        [class.selected]="hero === selectedHero">
      <span class="badge">{{hero.id}}</span>
      <span>{{hero.name}}</span>
      <button class="delete"
        (click)="delete(hero); $event.stopPropagation()">x</button>
    </li>
    In addition to calling the component's delete() method, the delete button's click handler code stops the propagation of the click event—you don't want the <li> click handler to be triggered because doing so would select the hero that the user will delete.

    Observables

    Each Http service method returns an Observable of HTTP Response objects.

    The HeroService converts that Observable into a Promise and returns the promise to the caller. This section shows you how, when, and why to return the Observable directly.

    Add the ability to search by name

    You're going to add a hero search feature to the Tour of Heroes. As the user types a name into a search box, you'll make repeated HTTP requests for heroes filtered by that name.

    Start by creating HeroSearchService that sends search queries to the server's web API.

    HeroSearchComponent

    Create a HeroSearchComponent that calls the new HeroSearchService.

    The component template is simple—just a text box and a list of matching search results.

    hero-search.component.html
    <div id="search-component">
      <h4>Hero Search</h4>
      <input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
      <div>
        <div *ngFor="let hero of heroes | async"
             (click)="gotoDetail(hero)" class="search-result" >
          {{hero.name}}
        </div>
      </div>
    </div>

    As the user types in the search box, a keyup event binding calls the component's search() method with the new search box value.
    As expected, the *ngFor repeats hero objects from the component's heroes property.
    But as you'll soon see, the heroes property is now an Observable of hero arrays, rather than just a hero array. The *ngFor can't do anything with an Observable until you route it through the async pipe (AsyncPipe). The async pipe subscribes to the Observable and produces the array of heroes to *ngFor.

    Create the HeroSearchComponent class and metadata.

    Search terms

    Focus on the searchTerms:
    private searchTerms = new Subject<string>();

    // Push a search term into the observable stream.
    search(term: string): void {
      this.searchTerms.next(term);
    }
    A Subject is a producer of an observable event stream; searchTerms produces an Observable of strings, the filter criteria for the name search.
    Each call to search() puts a new string into this subject's observable stream by calling next().

    • debounceTime(300) waits until the flow of new string events pauses for 300 milliseconds before passing along the latest string. You'll never make requests more frequently than 300ms.
    • distinctUntilChanged ensures that a request is sent only if the filter text changed.
    • switchMap() calls the search service for each search term that makes it through debounce and distinctUntilChanged. It cancels and discards previous search observables, returning only the latest search service observable.
     With the switchMap operator (formerly known as flatMapLatest), every qualifying key event can trigger an http() method call. Even with a 300ms pause between requests, you could have multiple HTTP requests in flight and they may not return in the order sent.
    switchMap() preserves the original request order while returning only the observable from the most recent http method call. Results from prior calls are canceled and discarded.
    If the search text is empty, the http() method call is also short circuited and an observable containing an empty array is returned.
    Note that until the service supports that feature, canceling the HeroSearchService Observable doesn't actually abort a pending HTTP request. For now, unwanted results are discarded.

    Add the search component to the dashboard

    Add the hero search HTML element to the bottom of the DashboardComponent template.

    Summary

    You're at the end of your journey, and you've accomplished a lot.

    • You added the necessary dependencies to use HTTP in the app.
    • You refactored HeroService to load heroes from a web API.
    • You extended HeroService to support post(), put(), and delete() methods.
    • You updated the components to allow adding, editing, and deleting of heroes.
    • You configured an in-memory web API.
    • You learned how to use Observables.

    From: https://angular.io/guide/quickstart