美文网首页
angular4 官网英雄指南04

angular4 官网英雄指南04

作者: 漫漫江雪 | 来源:发表于2017-07-25 17:26 被阅读0次

    把服务和组件改为用 Angular 的 HTTP 服务实现
    1、app.module.ts中导入HttpModule模块

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import {FormsModule} from '@angular/forms';
    import {HttpModule} from '@angular/http';
    
    import { AppComponent } from './app.component';
    import { HeroDetailComponent } from './hero-detail/hero-detail.component';
    
    import {HeroService} from './hero.service';
    import { HeroesComponent } from './heroes/heroes.component';
    import { DashboardComponent } from './dashboard/dashboard.component';
    
    import {AppRoutingModule} from './app-routing.module';
    
    @NgModule({
      declarations: [
        AppComponent,
        HeroDetailComponent,
        HeroesComponent,
        DashboardComponent
      ],
      imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        AppRoutingModule
      ],
      providers: [HeroService],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    2、模拟WebAPI
    要使用 angular-in-memory-web-api 首先要 npm install


    Paste_Image.png

    app.module.ts被修改成如下:

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import {FormsModule} from '@angular/forms';
    import {HttpModule} from '@angular/http';
    
    import { AppComponent } from './app.component';
    import { HeroDetailComponent } from './hero-detail/hero-detail.component';
    
    import {HeroService} from './hero.service';
    import { HeroesComponent } from './heroes/heroes.component';
    import { DashboardComponent } from './dashboard/dashboard.component';
    
    import {AppRoutingModule} from './app-routing.module';
    
    // Imports for loading & configuring the in-memory web api
    import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
    import { InMemoryDataService }  from './in-memory-data.service';
    
    @NgModule({
      declarations: [
        AppComponent,
        HeroDetailComponent,
        HeroesComponent,
        DashboardComponent
      ],
      imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        //InMemoryWebApiModule将Http客户端默认的后端服务 — 这是一个辅助服务,负责与远程服务器对话 — 替换成了内存 Web API服务
        InMemoryWebApiModule.forRoot(InMemoryDataService),
        AppRoutingModule
      ],
      providers: [HeroService],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    in-memory-data.service.ts

    import { InMemoryDbService } from 'angular-in-memory-web-api';
    export class InMemoryDataService implements InMemoryDbService {
      createDb() {
        let heroes = [
          {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};
      }
    }
    

    修改hero.service.ts服务

    import { Injectable } from '@angular/core';
    import {Headers,Http} from '@angular/http';
    import 'rxjs/add/operator/toPromise';
    
    import {Hero} from './hero';
    import {HEROES} from './mock-heroes';
    
    @Injectable()
    export class HeroService {
      private heroesUrl:string='api/heroes';   //URL to web api
      constructor(private http:Http){
    
      }
      getHero(id: number): Promise<Hero> {
        //return this.getHeroes().then(heroes => heroes.find(hero => hero.id === id));
        const url = `${this.heroesUrl}/${id}`;
        return this.http.get(url)
          .toPromise()
          .then(response => response.json().data as Hero)
          .catch(this.handleError);
      }
      getHeroes():Promise<Hero[]>{
        //return Promise.resolve(HEROES);
        return this.http.get(this.heroesUrl)
          .toPromise()
          .then(response=>response.json().data as Hero[])
          .catch(this.handleError);
      }
      getHeroesSlowly(): Promise<Hero[]> {
        return new Promise(resolve => {
          // Simulate server latency with 2 second delay
          setTimeout(() => resolve(this.getHeroes()), 2000);
        });
      }
      private handleError(error:any):Promise<any>{
        console.error('An error occurred',error);
        return Promise.reject(error.message||error);
      }
    }
    

    3、更新英雄详情
    先在英雄详情模板的底部添加一个保存按钮,它绑定了一个click事件,事件绑定会调用组件中一个名叫save()的新方法:

    <button (click)="save()">Save</button>
    //hero-detail.component.ts中添加保存方法
    save(): void {
      this.heroService.update(this.hero)
        .then(() => this.goBack());
    }
    

    hero.service.ts修改

    import { Injectable } from '@angular/core';
    import {Headers,Http} from '@angular/http';
    import 'rxjs/add/operator/toPromise';
    
    import {Hero} from './hero';
    import {HEROES} from './mock-heroes';
    
    @Injectable()
    export class HeroService {
      private heroesUrl:string='api/heroes';   //URL to web api
      private headers=new Headers({'Content-Type':'application/json'});
      constructor(private http:Http){
    
      }
      getHero(id: number): Promise<Hero> {
        //return this.getHeroes().then(heroes => heroes.find(hero => hero.id === id));
        const url = `${this.heroesUrl}/${id}`;
        return this.http.get(url)
          .toPromise()
          .then(response => response.json().data as Hero)
          .catch(this.handleError);
      }
      getHeroes():Promise<Hero[]>{
        //return Promise.resolve(HEROES);
        return this.http.get(this.heroesUrl)
          .toPromise()
          .then(response=>response.json().data as Hero[])
          .catch(this.handleError);
      }
      getHeroesSlowly(): Promise<Hero[]> {
        return new Promise(resolve => {
          // Simulate server latency with 2 second delay
          setTimeout(() => resolve(this.getHeroes()), 2000);
        });
      }
      private handleError(error:any):Promise<any>{
        console.error('An error occurred',error);
        return Promise.reject(error.message||error);
      }
      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);
      }
      create(name:string):Promise<Hero>{
        return this.http
          .post(this.heroesUrl,JSON.stringify({name: name}), {headers: this.headers})
          .toPromise()
          .then(res=>res.json().data as Hero)
          .catch(this.handleError);
      }
      
      delete(id: number): Promise<void> {
        const url = `${this.heroesUrl}/${id}`;
        return this.http.delete(url, {headers: this.headers})
          .toPromise()
          .then(() => null)
          .catch(this.handleError);
      }
    }
    

    heroes.component.ts修改

    import { Component,OnInit } from '@angular/core';
    import {Router} from '@angular/router';
    import {Hero} from '../hero';
    import {HeroDetailComponent} from '../hero-detail/hero-detail.component';
    import {HeroService} from '../hero.service';
    
    @Component({
      selector: 'my-heroes',
      template:`  
        <div>
          <label>Hero name:</label> <input #heroName />
          <button (click)="add(heroName.value); heroName.value=''">
            Add
          </button>
        </div>
        <ul class="heroes">
          <li *ngFor="let hero of heroes" 
          (click)="onSelect(hero)"
          [class.selected]="hero === selectedHero">
            <span class="badge">{{hero.id}}</span> {{hero.name}}
            <button class="delete" (click)="delete(hero); $event.stopPropagation()">x</button>
          </li>
        </ul>
        <div *ngIf="selectedHero">
          <h2>
            {{selectedHero.name | uppercase}} is my hero
          </h2>
          <button (click)="gotoDetail()">View Details</button>
        </div>
      `,
      styleUrls:['./heroes.component.css']
    })
    export class HeroesComponent implements OnInit {
      heroes:Hero[];
      selectedHero:Hero;
      constructor(private heroService:HeroService,private router:Router){
    
      }
      onSelect(hero:Hero):void{
        this.selectedHero=hero;
      }
      getHeroes():void{
        this.heroService.getHeroes().then(heroes => this.heroes = heroes);
      }
      ngOnInit(){
        this.getHeroes();
      }
      gotoDetail(): void {
        this.router.navigate(['/detail', this.selectedHero.id]);
      }
      add(name:string):void{
        name=name.trim();
        if(!name) return;
        this.heroService.create(name)
          .then(hero=>{
            this.heroes.push(hero);
            this.selectedHero=null;
          });
      }
      
      delete(hero:Hero):void{
        this.heroService
          .delete(hero.id)
          .then(() => {
            this.heroes = this.heroes.filter(h => h !== hero);
            if (this.selectedHero === hero) { this.selectedHero = null; }
          });
      }
    }
    

    4、为英雄指南添加英雄搜索
    创建hero-search.service.ts服务 ng g service hero-search

    import { Injectable } from '@angular/core';
    import {Http} from '@angular/http';
    
    import {Observable} from 'rxjs/observable';
    import 'rxjs/add/operator/map';
    import {Hero} from './hero';
    
    @Injectable()
    export class HeroSearchService {
    
      constructor(private http:Http) { }
      search(term:string):Observable<Hero[]>{
        return this.http.get(`app/heroes/?name=${term}`)
          .map(response=>response.json().data as Hero[]);
      }
    }
    

    再创建一个新的hero-search.component.ts组件
    ng g component hero-search

    import { Component, OnInit } from '@angular/core';
    import { Router }            from '@angular/router';
    import { Observable }        from 'rxjs/Observable';
    import { Subject }           from 'rxjs/Subject';
    // Observable class extensions
    import 'rxjs/add/observable/of';
    // Observable operators
    import 'rxjs/add/operator/catch';
    import 'rxjs/add/operator/debounceTime';
    import 'rxjs/add/operator/distinctUntilChanged';
    import { HeroSearchService } from '../hero-search.service';
    import { Hero } from '../hero';
    @Component({
      selector: 'hero-search',
      templateUrl: './hero-search.component.html',
      styleUrls: [ './hero-search.component.css' ],
      providers: [HeroSearchService]
    })
    export class HeroSearchComponent implements OnInit {
      heroes: Observable<Hero[]>;
      private searchTerms = new Subject<string>();
      constructor(
        private heroSearchService: HeroSearchService,
        private router: Router) {}
      // Push a search term into the observable stream.
      search(term: string): void {
        this.searchTerms.next(term);
      }
      ngOnInit(): void {
        this.heroes = this.searchTerms
          .debounceTime(300)        // wait 300ms after each keystroke before considering the term
          .distinctUntilChanged()   // ignore if next search term is same as previous
          .switchMap(term => term   // switch to new observable each time the term changes
            // return the http search observable
            ? this.heroSearchService.search(term)
            // or the observable of empty heroes if there was no search term
            : Observable.of<Hero[]>([]))
          .catch(error => {
            // TODO: add real error handling
            console.log(error);
            return Observable.of<Hero[]>([]);
          });
      }
      gotoDetail(hero: Hero): void {
        let link = ['/detail', hero.id];
        this.router.navigate(link);
      }
    }
    

    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>
    

    hero-search.component.css

    .search-result{
      border-bottom: 1px solid gray;
      border-left: 1px solid gray;
      border-right: 1px solid gray;
      width:195px;
      height: 16px;
      padding: 5px;
      background-color: white;
      cursor: pointer;
    }
    .search-result:hover {
      color: #eee;
      background-color: #607D8B;
    }
    #search-box{
      width: 200px;
      height: 20px;
    }
    

    为仪表盘添加搜索组件
    dashboard.component.html

    <h3>Top Heroes</h3>
    <div class="grid grid-pad">
      <a *ngFor="let hero of heroes"  [routerLink]="['/detail', hero.id]"  class="col-1-4">
        <div class="module hero">
          <h4>{{hero.name}}</h4>
        </div>
      </a>
    </div>
    <hero-search></hero-search>
    

    运行结果:


    Paste_Image.png

    相关文章

      网友评论

          本文标题:angular4 官网英雄指南04

          本文链接:https://www.haomeiwen.com/subject/fqwwkxtx.html