In this post, we are going to see how to solve one design pattern challenge.

The challenge is what we a simplest way to find out the children elements which belongs to Animals, which belongs to Materials inside the container component.

  <app-animals>
<cat></cat>
<dog></dog>
<rock></rock>
<fox></fox>
<viking></viking>
</app-animals>

As we can see that:

  Animals are <cat>, <dog>, <fox>, <viking>.

Material is <rock>.

1. First way we might use is Tamplate Ref:

<cat  #item></cat>
<fox #item></fox>
  // #item Ref
   @ContentChildren('item') itemRefsQL: QueryList<any>>
   const items = this.itemRefsQL.toArray();

It will work, but the problem for this solution is that, the container should know what children it has. Also the chance that I might mis-mark the component.

2. We can use 'directive' + {read: ElementRef}:

animal.directive.ts:

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

@Directive({
// tslint:disable-next-line:directive-selector
selector: '[animal]'
})
export class AnimalDirective {}
<cat animal></cat>
<dog animal></dog>
@ContentChildren(AnimalDirective, {read: ElementRef}) directiveElementsQL: QueryList<ElementRef>;
const directiveElements = this.directiveElementsQL.toArray();

Here without {read: ElementRef}, it won't work. We need it to tell Angular we are actually looking for the host element of the directive. Not direcitve itself.

But still the same problem as Tempalte Ref, we need to mark in the template to tell which component we need.

3.  Similar to using directive only, but {read: <interface>}.

We create a Animal interface and the component implements Animal interface.

animal.ts:

export abstract class Animal {
name: string;
abstract speak(): void;
abstract clear(): void;
}

dog.component.ts:

import { Component } from '@angular/core';
import { Animal } from './animal'; @Component({
// tslint:disable-next-line:component-selector
selector: 'dog',
template: `
<div>
<img src="../assets/dog.jpg"/>
<h3>{{saying}}</h3>
</div>
`,
})
// Subclasses Animal
export class DogComponent extends Animal { name = 'Dog';
saying: string; speak() {
this.saying = 'Woof';
} clear() {
this.saying = '';
} }

Now what we can do is Query by Animal interface in the contianer component:

<cat  animal ></cat>
  @ContentChildren(AnimalDirective, {read: Animal}) directiveAnimalsQL: QueryList<Animal>;
const directiveAnimals = this.directiveAnimalsQL.toArray();
console.log("directiveAnimals", directiveAnimals);
/*
CatComponent {injector: Injector_, name: "Cat"}
DogComponent {name: "Dog"}
FoxComponent {name: "Fox"}
VikingComponent {name: "Viking"}
*/

4. Recommended: Finally we come to our recommended solution.

Using alias Injection of the component itself.

import { Component } from '@angular/core';
import { Animal } from './animal'; @Component({
// tslint:disable-next-line:component-selector
selector: 'fox',
template: `
<div>
<img src="../assets/fox.jpeg"/>
<h3>{{saying}}</h3>
</div>
`,
providers: [
{ provide: Animal, useExisting: FoxComponent }
]
})
export class FoxComponent implements Animal {
name = 'Fox';
saying: string; speak() {
this.saying = 'ring-ding-ding-ding-dingedinging';
} clear() {
this.saying = '';
} }

For the animals related component, we inject the provider 'useExisting', so it always refer to the same instance. And we use interface Animal as alias.

Now, our container can be really clean:

      <cat ></cat>
<dog></dog>
  // Any projected component with an Animal "interface" in its injector
   import { Animal } from './animal';
  @ContentChildren(Animal) animalsQL: QueryList<Animal>;

  ngAfterContentInit() {
const animals = this.animalsQL.toArray();
}

Talk, Github

[Angular] Advanced DI的更多相关文章

  1. [Angular 2] DI in Angular 2 - 1

    Orgial aritial --> Link The problem with Angular 1 DI: Angular 2 DI: Solve the singletons problem ...

  2. [Angular] Angular Advanced Features - ng-template , ng-container, ngTemplateOutlet

    Previously we have tab-panel template defined like this: <ul class="tab-panel-buttons" ...

  3. 来自 Thoughtram 的 Angular 2 系列资料

    Angular 2 已经正式 Release 了,Thoughtram 已经发布了一系列的文档,对 Angular 2 的各个方面进行深入的阐释和说明. 我计划逐渐将这个系列翻译出来,以便对大家学习 ...

  4. Angular概念纵览

    Conceptual Overview Template(模板): HTML with additional markup (就是增加了新的标记的HTML) Directive(指令): extend ...

  5. (七)理解angular中的module和injector,即依赖注入

    (七)理解angular中的module和injector,即依赖注入 时间:2014-10-10 01:16:54      阅读:63060      评论:1      收藏:0      [点 ...

  6. angular问题总结与反思

    因为工作中实际开发需要,才开始接触angular框架.从当初的比葫芦画瓢,被各种问题.概念折磨摧残,到现在有一定的了解认识,觉得有必要将自己的认识进行简单的总结.不到位的地方还望多多包涵. 1.双向数 ...

  7. [Angular 2] Understanding @Injectable

    In order to resolve a dependency, Angular’s DI uses type annotations. To make sure these types are p ...

  8. [Angular 2] Factory Provider with dependencies

    This lesson discusses when and how to add dependencies, resolved by Angular’s DI, to factory provide ...

  9. [Angular 2] Factory Provider

    In this lesson, we discuss how and when to use factory providers, to enable dependencies that should ...

随机推荐

  1. the user must supply a jdbc connection 错误解决方法

    转自:https://blog.csdn.net/actionzh/article/details/54200451 今天在配置hibernate之后,进行添加数据测试时,运行中报出了 the use ...

  2. 机器人走迷宫(dfs)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1590 #include <stdio.h ...

  3. LeetCode刷题 1. Two Sum 两数之和 详解 C++语言实现 java语言实现

    1. Two Sum 两数之和 Given an array of integers, return indices of the two numbers such that they add up ...

  4. DotNetCasClient加载失败问题分析

    最近公司在接入整理单点登录方案的时候,选择了CAS方案,实际版本采用了4.0.当我们把服务端附属完毕,基于.NET平台Web版的客户端DotNetCasClient进行定制化修改后,在测试环境通过.然 ...

  5. itext 生成pdf文档 小结(自己备忘)

    1.引入maven <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf& ...

  6. MySQL定期执行任务相关问题

    在sqlyog某数据库下的事件里新建事件,并写入一下代码: DELIMITER $$ ALTER DEFINER=`root`@`%` EVENT `0` ON SCHEDULE EVERY 24 H ...

  7. RecyclerView 通用 Adapter

    先看使用方法

  8. node post和get请求原理

    重要:GET和POST请求他们都是上行请求,都是把数据从浏览器带向服务器的方式, GET 请求实际上就是识别URL中的querystring部分POST请求,一般用来发送大量的内容,此时node非常害 ...

  9. 【Linux】磁盘分区

    我们在Linux操作过程中,可能会遇到磁盘分区的问题.这篇文章是对/dev/sdb 这块磁盘进行分区. linux分区不同于windows,linux下硬盘设备名为(IDE硬盘为hdx(x为从a—d) ...

  10. MySQL 优化之 index_merge (索引合并)

    深入理解 index merge 是使用索引进行优化的重要基础之一.理解了 index merge 技术,我们才知道应该如何在表上建立索引. 1. 为什么会有index merge 我们的 where ...