将组件中的依赖项注入附加到已附加的注入

时间:2019-05-17 12:33:26

标签: angular dependency-injection angular-material inject

我正在使用Angular Material样式将按钮组件(AddButtonComponent)动态地附加到另一个组件(ParentComponent)的DOM上。如果我通常使用<button matButton>A button</button>在模板中创建按钮,则按钮的样式会完美。如果我动态创建它,它也会被设置样式。

现在,我需要注入一个字符串以将类名附加到我的按钮上,但是如果使用自定义Injector,它将丢失所有样式。我认为当我注入字符串时,它会覆盖该注入器当前的应用注入。

我尝试将ParentComponent注入器添加到parent属性中,但是也没有用。

我在做什么错了?

(很明显,我可以调用instance中的ElementRef并设置属性值,但这很丑陋。我相信可以实现。)

这是一个代码示例:

import {
    Component,
    OnInit,
    Optional,
    Inject,
    Injector,
    InjectionToken,
    ElementRef,
    ViewContainerRef,
    ComponentFactoryResolver,
} from '@angular/core';

export const CLASS_INJECTION: InjectionToken<string> = new InjectionToken<string>('ClassInjection');

@Component({
    selector: 'app-add-button`,
    template: '<button matButton [class]="classInjection">A button</button>',
    styles: []
})
export class AddButtonComponent implements OnInit {

    constructor(@Optional() @Inject(CLASS_INJECTION) public classInjection: string) { }

}

@Component({
    selector: 'app-parent-component',
    template: '<button matButton>Button styled</button>',
    styles: []
})
export class ParentComponent implements OnInit {

    constructor(
        private _injector: Injector,
        private componentFactoryResolver: ComponentFactoryResolver,
        private viewContainerRef: ViewContainerRef
    ) { }

    ngOnInit() {
        const addButtonComponentFactory = this.componentFactoryResolver.resolveComponentFactory(AddButtonComponent);
        const addButtonComponentRef = this.viewContainerRef.createComponent(addButtonComponentFactory, undefined, Injector.create({
            providers: [{provide: ELEMENT_TYPE, useValue: widget.type === 'column' ? 'SECTION' : 'MODULE'}],
            parent: this._injector
        }));
        // <Code to add element into DOM...>
    }

}

1 个答案:

答案 0 :(得分:1)

<button matButton [class]="classInjection">A button</button>

matButton在创建时将分配CSS类,但是您使用的[class]绑定将替换所有现有的CSS类。因此,材料设计CSS样式丢失了。如果您在Chrome检查器中查看,则会看到它们已被删除。

如果您知道仅使用SECTIONMODULE,请使用[class.style]绑定来选择性地添加或删除特定样式。

<button matButton [class.SECTION]="classInjection === 'SECTION'"
                  [class.MODULE]="classInjection === 'MODULE'">A button</button>

如果您不知道CSS样式是什么,则必须手动添加它们。可以通过通过<button>访问@ViewChild元素,然后手动添加CSS样式来完成。

@Component({
    selector: 'app-add-button',
    template: '<button matButton>A button</button>',
    styles: []
})
export class AddButtonComponent implements OnInit {

    @ViewChild(MatButton, {read: ElementRef})
    public btn: ElementRef<HTMLElement>;

    constructor(@Optional() @Inject(CLASS_INJECTION) public classInjection: string) {
    }

    public ngOnInit(): void {
        this.btn.nativeElement.classList.add(this.classInjection);
    }
}

过去使用[class]时我感到非常沮丧,因为它会覆盖alls样式,并且没有其他替代方法可以使用。 [class][ngClass]的行为相同,如果必须频繁执行上述操作,则可以编写一个名为[addClass]的自定义指令,该指令仅附加CSS样式。