[Angular] Control the dependency lookup with @Host, @Self, @SkipSelf and @Optional

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.

复制代码
export class PersonComponent implements OnInit {
  constructor(
    @Optional()
    public logger: LoggerService
  ) {}

  ngOnInit() {}

  doLog() {
    if (this.logger) {
      this.logger.log('Message from PersonComponent');
    } else {
      console.log('sorry, no logger available');
    }
  }
}
复制代码

 

@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.

复制代码
// Child
@Component({
  selector: 'app-person',
  template: `
    <div style="border:1px;">
      <p *ngIf="logger === null">I don't have a logger</p>
      <button (click)="doLog()">write log</button>
    </div>
  `
   providers: [
     {
       provide: LoggerService,
       useFactory: loggerFactory('PersonComponent')
     }
   ]
})
export class PersonComponent implements OnInit {
  constructor(
    @SkipSelf()
    @Optional()
    public logger: LoggerService
  ) {}

  ngOnInit() {}

  doLog() {
    if (this.logger) {
      this.logger.log('Message from PersonComponent');
    } else {
      console.log('sorry, no logger available');
    }
  }
}
复制代码
复制代码
// parent

@Component({
  selector: 'app-root',
  template: `
    <h1>Angular Services</h1>
    <app-person></app-person>
  `,
  providers: [
    {
      provide: LoggerService,
      useFactory: loggerFactory('AppComponent')
    }
  ]
})
export class AppComponent {}
复制代码

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

 

@Self():

Only using the provider for its own component.

复制代码
@Component({
  selector: 'app-person',
  template: `
    <div style="border:1px;">
      <p *ngIf="logger === null">I don't have a logger</p>
      <button (click)="doLog()">write log</button>
    </div>
  `
  // providers: [
  //   {
  //     provide: LoggerService,
  //     useFactory: loggerFactory('PersonComponent')
  //   }
  // ]
})
export class PersonComponent implements OnInit {
  constructor(
    @Self()
    @Optional()
    public logger: LoggerService
  ) {}

  ngOnInit() {}

  doLog() {
    if (this.logger) {
      this.logger.log('Message from PersonComponent');
    } else {
      console.log('sorry, no logger available');
    }
  }
}
复制代码

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.

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

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.

@Directive({
  selector: 'highlighted'
})
export class Hightlighted {
  // Use the provide inject directly into the host component
  constructor (@Optional @Host private myService: MyService) {}
}

 

 

Lesson

posted @   Zhentiw  阅读(1035)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2017-01-21 [TypeScript] Catch unsafe use of "this" in TypeScript functions
2015-01-21 [AngularJS] angular-schema-form -- 1
点击右上角即可分享
微信分享提示