Very differently to AngularJS (v1.x), Angular now has a hierarchical dependency injector. That allows to specify service definitions as well as the service lifetime at various levels in our application. Whenever a service is requested, Angular will walk up the component tree and search for a matching definition. While in most cases that's perfectly fine, often you may want to take control over the dependency lookup. In this lesson we will learn how, by applying"@Host, @Self()@SkipSelf() and @Optional().

@Optional:

When using @Optional, it set logger to null if the LoggerService is not provided instead of error out.

  1. export class PersonComponent implements OnInit {
  2. constructor(
  3. @Optional()
  4. public logger: LoggerService
  5. ) {}
  6.  
  7. ngOnInit() {}
  8.  
  9. doLog() {
  10. if (this.logger) {
  11. this.logger.log('Message from PersonComponent');
  12. } else {
  13. console.log('sorry, no logger available');
  14. }
  15. }
  16. }

@SkipSelf:

If child component and parent component both using the same provider and we want to skip using child component's provider instead using parent's provider.

  1. // Child
  2. @Component({
  3. selector: 'app-person',
  4. template: `
  5. <div style="border:1px;">
  6. <p *ngIf="logger === null">I don't have a logger</p>
  7. <button (click)="doLog()">write log</button>
  8. </div>
  9. `
  10. providers: [
  11. {
  12. provide: LoggerService,
  13. useFactory: loggerFactory('PersonComponent')
  14. }
  15. ]
  16. })
  17. export class PersonComponent implements OnInit {
  18. constructor(
  19. @SkipSelf()
  20. @Optional()
  21. public logger: LoggerService
  22. ) {}
  23.  
  24. ngOnInit() {}
  25.  
  26. doLog() {
  27. if (this.logger) {
  28. this.logger.log('Message from PersonComponent');
  29. } else {
  30. console.log('sorry, no logger available');
  31. }
  32. }
  33. }
  1. // parent
  2.  
  3. @Component({
  4. selector: 'app-root',
  5. template: `
  6. <h1>Angular Services</h1>
  7. <app-person></app-person>
  8. `,
  9. providers: [
  10. {
  11. provide: LoggerService,
  12. useFactory: loggerFactory('AppComponent')
  13. }
  14. ]
  15. })
  16. export class AppComponent {}

SO in the end 'AppComponent ...' log message will appear in the console.

@Self():

Only using the provider for its own component.

  1. @Component({
  2. selector: 'app-person',
  3. template: `
  4. <div style="border:1px;">
  5. <p *ngIf="logger === null">I don't have a logger</p>
  6. <button (click)="doLog()">write log</button>
  7. </div>
  8. `
  9. // providers: [
  10. // {
  11. // provide: LoggerService,
  12. // useFactory: loggerFactory('PersonComponent')
  13. // }
  14. // ]
  15. })
  16. export class PersonComponent implements OnInit {
  17. constructor(
  18. @Self()
  19. @Optional()
  20. public logger: LoggerService
  21. ) {}
  22.  
  23. ngOnInit() {}
  24.  
  25. doLog() {
  26. if (this.logger) {
  27. this.logger.log('Message from PersonComponent');
  28. } else {
  29. console.log('sorry, no logger available');
  30. }
  31. }
  32. }

So if PersonComponent has provider defined, it will use its own provider and will not continue searching parent component.

Often @Self can use togerther with @Optional, so if the provider is not defined, then set it to null.

@Host:

When we have directive, we might need to use @Host.

  1. @Component({
  2. selector: 'my-comp',
  3. ...
  4. providers: [
  5. MyService // Must have, other directive cannot find it, throw error.
  6. ]
  7. })
  1. <my-comp highlighted />
  1. @Directive({
  2. selector: 'highlighted'
  3. })
  4. export class Hightlighted {
  5. // Use the provide inject directly into the host component
  6. constructor (@Host private myService: MyService) {}
  7. }

Because we cannot ensure that host element must have the Injection, if not, Angular will throw error, to prevent that, @Host normally work with @Optional together.

  1. @Directive({
  2. selector: 'highlighted'
  3. })
  4. export class Hightlighted {
  5. // Use the provide inject directly into the host component
  6. constructor (@Optional @Host private myService: MyService) {}
  7. }

Lesson

[Angular] Control the dependency lookup with @Host, @Self, @SkipSelf and @Optional的更多相关文章

  1. [Angular] Component's dependency injection

    An Angular service registered on the NgModule is globally visible on the entire application. Moreove ...

  2. [Angular Tutorial] 7-XHRs & Dependency Injection

    我们受够了在应用中用硬编码的方法嵌入三部电话!现在让我们用Angular内建的叫做$http的服务来从我们的服务器获取更大的数据集吧.我们将会使用Angular的依赖注入来为PhoneListCtrl ...

  3. [AngularFire] Angular File Uploads to Firebase Storage with Angular control value accessor

    The upload class will be used in the service layer. Notice it has a constructor for file attribute, ...

  4. How to achieve dialog with lookup control

    How to create a dialog with the lookup as a control, the other control SalesId ItemId lookup is the ...

  5. angular(常识)

    我觉得angularjs是前端框架,而jquery只是前端工具,这两个还是没有可比性的. 看知乎上关于jquery和angular的对比http://www.zhihu.com/question/27 ...

  6. Angular 4+ 修仙之路

    Angular 4.x 快速入门 Angular 4 快速入门 涉及 Angular 简介.环境搭建.插件表达式.自定义组件.表单模块.Http 模块等 Angular 4 基础教程 涉及 Angul ...

  7. Dependency Injection

    Inversion of Control - Dependency Injection - Dependency Lookup loose coupling/maintainability/ late ...

  8. Hosting custom WPF calendar control in AX 2012

    原作者: https://community.dynamics.com/ax/b/axilicious/archive/2013/05/20/hosting-custom-wpf-calendar-c ...

  9. Spring (一) IOC ( Inversion Of Control )

    前序 现在小米手机很火就还拿小米手机来举例子,上一篇写的关于SSH框架搭建是从小米手机公司内个整个流程方面来考虑,如何提高效率生产效率,这篇博客主要从公司外部环境说明如何提高生产效率,那么怎么才能提高 ...

随机推荐

  1. 在 C# 中通过 P/Invoke 调用Win32 DLL

    在 C# 中通过 P/Invoke 调用Win32 DLL 发布日期 : 1/13/2005 | 更新日期 : 1/13/2005 Jason Clark 下载本文的代码: NET0307.exe ( ...

  2. python中的迭代器详解

    #原创,转载请先联系 理论性的东西有点枯燥,耐心点看- 1.迭代是什么? 我们知道可以对list,tuple,dict,str等数据类型使用for...in的循环语法,从其中依次取出数据,这个过程叫做 ...

  3. 工作管理 (job control)

    这个工作管理 (job control) 是用在 bash 环境下的,也就是说:『当我们登入系统取得创建的 bash shell 进程之后,在该bush下同时进行多个工作的行为管理 』. 而所有创建的 ...

  4. 记一次Laravel定时任务导致日志没有写入权限的坑

    问题:用laravel开发定时任务时,发生了日志没有写入权限导致项目打不开的问题 原因:linux的添加定时任务时默认是当前登录用户,我定时任务会生成日志 crontab: kernel: 生成日志的 ...

  5. [BZOJ1492] [NOI2007]货币兑换Cash 斜率优化+cdq/平衡树维护凸包

    1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 5907  Solved: 2377[Submit][Sta ...

  6. hdu5076

    好题,首先观察可得w[i][j]选择只有可能两种,一种比阀值大,一种比阀值小 比阀值大就一定选满足条件最大的w,比阀值小同样一定选满足条件最大的w 那么一个最小割模型就呼之欲出了,注意w可能是负数那么 ...

  7. [centos6.5] 把xampp的htdocs改为其他目录

    vim /opt/lampp/etc/httpd.conf DocumentRoot "/opt/lampp/htdocs" 改为 DocumentRoot "/var/ ...

  8. (11)python 模块和包

    一.导入模块和包 模块相当于一个.py文件,包相当于带有个__init__.py一个文件夹,既可按模块导入也可按包导入. 1.导入模块或包 import 包名或模块名 (as 别名),包名或模块名 ( ...

  9. 欧拉图和欧拉圈-Play On Words(UVa10129)

    欧拉路和欧拉圈,简言之就是,从无向图的一个结点出发,走一条路/圈,每条边恰好经过一次,即一笔画问题 欧拉定理:一个无向图最多只有两个奇结点,那么我们就从一个奇结点出发,到另一个结点为之,一定有一条欧拉 ...

  10. hdu6138(后缀数组)

    hdu6138 题意 给出若干个字符串,每次查询两个字符串,求两个字符串的公共子串且在给出的某一个字符串中作为前缀的最大长度. 分析 求公共子串:后缀数组 判断前缀:字典树 求完后缀数组,遍历下 \( ...