首页 > 解决方案 > 是否可以将指令应用于另一个组件模板中的组件?

问题描述

我有一个组件A:

@Component({
    selector: 'component-a',
    template: `<span>{{sampleText}}</span>`,
    styles: []
})
export class ComponentA implements OnInit {

    sampleText: string = 'ComponentA';

    constructor() {}

    ngOnInit() {
    }
}

和 ComponentA 的指令:

@Directive({
  selector: '[DirectiveForA]'
})
export class DirectiveForA implements OnInit {

    @Input('customText') customText: string;

    constructor(private componentA: ComponentA) {        
    }

    ngOnInit() {
        this.componentA.sampleText = this.customText;
    }
}

我可以为此应用我的指令:

<component-a>
    <ng-template DirectiveForA customText="injectedText"></ng-template>
</component-a>

但是,我有另一个 ComponentB,里面有一个 ComponentA:

@Component({
    selector: 'component-b',
    template: `<component-a></component-a>`,
    styles: []
})
export class ComponentB implements OnInit {

    @ViewChild(ComponentA, { static: false }) componentA: ComponentA;

    constructor() {}

    ngOnInit() {
    }
}

当像这样使用 ComponentB 时,我想将该指令应用于其中的 ComponentA :

<component-b>
    <ng-template DirectiveForA customText="injectedText!"></ng-template>
</component-b>

角抱怨:

ERROR NullInjectorError: StaticInjectorError(AppModule)[DirectiveForA -> ComponentA]: 
    StaticInjectorError(Platform: core)[DirectiveForA -> ComponentA]: 
    NullInjectorError: No provider for ComponentA!

问题:我有办法让它工作吗?如果没有,那么更好的做法是什么?
(在我的例子中,ComponentA 实际上是一个网格,DirectiveA 是某个网格​​列的模板。ComponentB 实际上是带有输入表单的网格。ComponentB 使用非常频繁,但我想在 ComponentA 中自定义一个列。)

标签: angular

解决方案


我终于找到了一种使用可选注入的方法。

@Directive({
  selector: '[DirectiveForA]'
})
export class DirectiveForA implements OnInit {

    @Input('customText') customText: string;
    private target: ComponentA;

    constructor(@Host() @Optional() public componentA: ComponentA, @Host() @Optional() public componentB: ComponentB) {
        if(componentA){
            this.target = componentA;
        }
        else if(componentB){
            this.target = componentB.componentA;
        }
    }

    ngOnInit() {
        if(this.target){
            this.target.sampleText = this.customText;
        }            
    }
}

推荐阅读