[Angular] Advanced DI
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
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
- @ContentChildren(Animal) animalsQL: QueryList<Animal>;
- ngAfterContentInit() {
- const animals = this.animalsQL.toArray();
- }
[Angular] Advanced DI的更多相关文章
- [Angular 2] DI in Angular 2 - 1
Orgial aritial --> Link The problem with Angular 1 DI: Angular 2 DI: Solve the singletons problem ...
- [Angular] Angular Advanced Features - ng-template , ng-container, ngTemplateOutlet
Previously we have tab-panel template defined like this: <ul class="tab-panel-buttons" ...
- 来自 Thoughtram 的 Angular 2 系列资料
Angular 2 已经正式 Release 了,Thoughtram 已经发布了一系列的文档,对 Angular 2 的各个方面进行深入的阐释和说明. 我计划逐渐将这个系列翻译出来,以便对大家学习 ...
- Angular概念纵览
Conceptual Overview Template(模板): HTML with additional markup (就是增加了新的标记的HTML) Directive(指令): extend ...
- (七)理解angular中的module和injector,即依赖注入
(七)理解angular中的module和injector,即依赖注入 时间:2014-10-10 01:16:54 阅读:63060 评论:1 收藏:0 [点 ...
- angular问题总结与反思
因为工作中实际开发需要,才开始接触angular框架.从当初的比葫芦画瓢,被各种问题.概念折磨摧残,到现在有一定的了解认识,觉得有必要将自己的认识进行简单的总结.不到位的地方还望多多包涵. 1.双向数 ...
- [Angular 2] Understanding @Injectable
In order to resolve a dependency, Angular’s DI uses type annotations. To make sure these types are p ...
- [Angular 2] Factory Provider with dependencies
This lesson discusses when and how to add dependencies, resolved by Angular’s DI, to factory provide ...
- [Angular 2] Factory Provider
In this lesson, we discuss how and when to use factory providers, to enable dependencies that should ...
随机推荐
- 曼哈顿距离 C++
template <class T1, class T2>double ManhattanDistance(std::vector<T1> &inst1, std::v ...
- Area(pick定理)
http://poj.org/problem?id=1265 题意:起始为(0,0),给出每个点的偏移量,求依次连接这些点形成的多边形边界上格点的个数. 思路:先将各个点的坐标求出存入,由pick定理 ...
- Django 创建新项目后要完成的几个步骤
首先,在过一遍创建新项目的步骤: -创建一个新项目 -建了数据库后要确定自己是用 mysql数据库 还是用 sqlite3数据库 -如果是mysql数据库,那一堆配置 -如果是sqlite3数据库, ...
- 混个脸熟 -- go
一.第一个项目:hello world src/day1/example1/main.go package main import "fmt" func main(){ fmt.P ...
- Django:提交表单报错:RuntimeError: You called this URL via POST, but the URL doesn’t end in a slash and you have A
Django:提交表单报错:RuntimeError: You called this URL via POST, but the URL doesn’t end in a slash and you ...
- D - Vanya and Fence
Problem description Vanya and his friends are walking along the fence of height h and they do not wa ...
- position中的absolute、fixed区别
absolute: 绝对定位,相对于body. fixed: 固定定位,相对于浏览器视窗,不随滚动条的滚动而滚动. 这两个属性概念比较模糊,一般在做左边列表菜单,右边内容区域的时候会用到这样的定位 ...
- WCF分佈式事務支持
WCF分佈式事務對Binding有要求,不支持BasicHttpBinding,BasicHttpContextBinding,NetPeerTcpBinding 要支持分佈式事務,需要進行以下配置: ...
- 编译Caffe-Win错误集锦
Caffe在Windows下编译还是遇到不少麻烦的... 1.visual studio 2013 error C2371: 'int8_t' : redefinition; 引入的unistd.h文 ...
- Mysql正则
摘自:http://www.runoob.com/mysql/mysql-regexp.html 模式 描述 ^ 匹配输入字符串的开始位置.如果设置了 RegExp 对象的 Multiline 属性, ...