angular2-chapter10

How angular 2 do DI

Check code at: https://github.com/wghglory/angular2-fundamental

when calling eventService, angular2 uses EventService class as key to do DI, it creates an instance of EventService, and assign it to eventService. (angular1 uses string as key to do DI)

export class CreateEventComponent {
    constructor(private eventService: EventService) { }
}

Using Third Party Global Services - The Problem

  • Now when we edit profile, change lastname or firstname, save, there is no any user-friendly popup. We want our toastr to do this job.
  • Our toastr service uses global variable declare let toastr: any, it comes from the index.html <script src="node_modules/toastr/build/toastr.min.js"></script>
  • We want a way that avoiding using global variable, and we don't want to create a toastrService to wrap up all its apis. jQuery has too many apis, we cannot wrap all apis.

Using OpaqueToken for DI

  1. Update common/toastr.service.ts
// import { Injectable } from '@angular/core'
//
// //I guess this local variable was assigned the global toastr variable
// declare let toastr: any
//
// @Injectable()
// export class ToastrService {
//
//     success(message: string, title?: string) {
//         toastr.success(message, title);
//     }
//     info(message: string, title?: string) {
//         toastr.info(message, title);
//     }
//     error(message: string, title?: string) {
//         toastr.error(message, title);
//     }
//     warning(message: string, title?: string) {
//         toastr.warning(message, title);
//     }
//
// }

import { OpaqueToken } from '@angular/core'

export let TOASTR_TOKEN = new OpaqueToken('toastr');

//not necessary if api is large, just for intellisense
export interface Toastr {
    success(message: string, title?: string): void;
    info(message: string, title?: string): void;
    error(message: string, title?: string): void;
    warning(message: string, title?: string): void;
}
  1. Register it in app.module.ts
// import { ToastrService } from './common/toastr.service'
+ import { TOASTR_TOKEN, Toastr } from './common/toastr.service'
+ declare let toastr: Toastr

@NgModule({
    imports: [...],
    declarations: [...],
    providers: [
        EventService,
        // ToastrService,
+        { provide: TOASTR_TOKEN, useValue: toastr },
        EventRouteActivator,
        {
            provide: 'canDeactivateCreateEvent',
            useValue: checkDirtyState
        },
        EventListResolver,
        AuthService
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }
  1. Remove all old ToastService in events-list component

Using the @Inject Decorator

profile.component.ts:

  1. import Inject, TOASTR_TOKEN, Toastr.
  2. @Inject(TOASTR_TOKEN) private toastr: Toastr, @Inject is angular DI, Toastr is typescript intellisense (not required)
  3. use the service: this.toastr.success('Profile saved successfully!')
+ import { Component, OnInit, Inject } from '@angular/core'
import { FormControl, FormGroup, Validators } from '@angular/forms'
import { AuthService } from './auth.service'
import { Router } from '@angular/router'

+ import { TOASTR_TOKEN, Toastr } from '../common/toastr.service'

@Component({
    templateUrl: 'app/user/profile.component.html',
    styles: [
        `
        em {float:right;color:#e05c65;padding-left:10px;}
        .error input{background-color:#e3c3c5;}
        .error ::-webkit-input-placeholder {color:#999;}
        .error ::-moz-placeholder {color:#999;}
        .error :-ms-input-placeholder {color:#999;}
        `
    ]
})
export class ProfileComponent implements OnInit {
+    constructor(private authService: AuthService, private router: Router, @Inject(TOASTR_TOKEN) private toastr: Toastr) { }

    profileForm: FormGroup
    private firstName: FormControl
    private lastName: FormControl

    ngOnInit() {
        this.firstName = new FormControl(this.authService.currentUser.firstName, [Validators.required, Validators.pattern('[a-zA-Z].*')])
        this.lastName = new FormControl(this.authService.currentUser.lastName, Validators.required)

        this.profileForm = new FormGroup({
            firstName: this.firstName,
            lastName: this.lastName
        })
    }

    cancel() {
        this.router.navigate(['events'])
    }

    saveProfile(formValues) {
        if (this.profileForm.valid) {
            this.authService.updateCurrentUser(formValues.firstName, formValues.lastName)
    +        this.toastr.success('Profile saved successfully!')
    -        // this.router.navigate(['events'])
        }
    }

    validateFirstName() {
        return this.firstName.valid || this.firstName.untouched
    }

    validateLastName() {
        return this.lastName.valid || this.lastName.untouched
    }
}

The useClass Provider

in app.module.ts:

Someday we might use { provide: logger, useClass: fileLogger }

providers: [
    EventService,
    // ToastrService,
    { provide: TOASTR_TOKEN, useValue: toastr },
    EventRouteActivator, //short hand of { provide: EventRouteActivator, useClass: EventRouteActivator },
    {
        provide: 'canDeactivateCreateEvent',
        useValue: checkDirtyState
    },
    EventListResolver,
    AuthService
],

The useExisting and useFactory Providers (rarely use)

You use Logger service. It's a big api which contains 30 methods, but you are going to use only 5 common methods

providers: [
    { provide: MinimalLogger, useExisting: Logger },
    { provide: MinimalLogger, useFactory: Logger },
],
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • PLEASE READ THE FOLLOWING APPLE DEVELOPER PROGRAM LICENSE...
    念念不忘的阅读 14,597评论 5 6
  • 童年时期父母的忽视与拒斥会对一个人的自信以及成年后的人际关系造成很大的负面影响,人们不断重复过去那些令人沮丧的经历...
    毛毛虫_3121阅读 8,067评论 0 4
  • 也许会很累 活在 别人 口中 你是没有根的自己 随风吹 守着春回大地露枝芽的诺 白天给了你向上生长的力量 你却非要...
    温图图阅读 1,774评论 0 0
  • 初识 印象中第一次看篮球比赛,是在五年级,2001年。那会我还没学会投篮,不知道AI,不知道科比。在我们那个地方,...
    程序熊大阅读 4,268评论 5 0
  • 自从今年六月一号选择开始跑步,断续地在跑,从开始的三公里到如今每次都是十公里左右,前两天和平邀我挑战半马,...
    荆棘鸟8810阅读 3,677评论 0 4