将组件中的依赖注入附加到已经附加的注入
Attach dependency injection in component to the already attached injections
我使用 Angular Material 将按钮组件 (AddButtonComponent
) 动态附加到另一个组件 (ParentComponent
) 的 DOM。如果我通常在模板中使用 <button matButton>A button</button>
创建按钮,按钮的样式就会完美。如果我动态创建它,它也会有样式。
现在,我需要注入一个字符串以将类名附加到我的按钮,但如果我使用自定义 Injector
,它会丢失所有样式。我认为当我注入我的字符串时,它会用那个注入器覆盖当前的应用程序注入。
我尝试将 ParentComponent
注入器添加到 parent
属性,但它也没有用。
我做错了什么?
(明明可以调用ElementRef
的instance
,设置属性值,但是太丑了,相信可以实现。)
这是一个代码示例:
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...>
}
}
<button matButton [class]="classInjection">A button</button>
matButton
将在创建时分配 CSS 类,但您使用的 [class]
绑定将 替换 所有现有 CSS 类。所以 Material 设计 CSS 样式丢失了。如果您查看 Chrome 检查器,您会发现它们已被删除。
如果您知道只会使用 SECTION
和 MODULE
,则使用 [class.style]
绑定有选择地添加或删除特定样式。
<button matButton [class.SECTION]="classInjection === 'SECTION'"
[class.MODULE]="classInjection === 'MODULE'">A button</button>
如果您不知道 CSS 样式是什么,则必须手动添加它们。这可以通过 @ViewChild
访问 <button>
元素然后手动添加 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]
时我感到非常沮丧,因为它会覆盖所有样式,而且没有其他方法可供使用。 [class]
和 [ngClass]
具有相同的行为,如果您必须经常执行上述操作,您可以编写一个名为 [addClass]
的自定义指令,它仅附加 CSS 样式。
我使用 Angular Material 将按钮组件 (AddButtonComponent
) 动态附加到另一个组件 (ParentComponent
) 的 DOM。如果我通常在模板中使用 <button matButton>A button</button>
创建按钮,按钮的样式就会完美。如果我动态创建它,它也会有样式。
现在,我需要注入一个字符串以将类名附加到我的按钮,但如果我使用自定义 Injector
,它会丢失所有样式。我认为当我注入我的字符串时,它会用那个注入器覆盖当前的应用程序注入。
我尝试将 ParentComponent
注入器添加到 parent
属性,但它也没有用。
我做错了什么?
(明明可以调用ElementRef
的instance
,设置属性值,但是太丑了,相信可以实现。)
这是一个代码示例:
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...>
}
}
<button matButton [class]="classInjection">A button</button>
matButton
将在创建时分配 CSS 类,但您使用的 [class]
绑定将 替换 所有现有 CSS 类。所以 Material 设计 CSS 样式丢失了。如果您查看 Chrome 检查器,您会发现它们已被删除。
如果您知道只会使用 SECTION
和 MODULE
,则使用 [class.style]
绑定有选择地添加或删除特定样式。
<button matButton [class.SECTION]="classInjection === 'SECTION'"
[class.MODULE]="classInjection === 'MODULE'">A button</button>
如果您不知道 CSS 样式是什么,则必须手动添加它们。这可以通过 @ViewChild
访问 <button>
元素然后手动添加 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]
时我感到非常沮丧,因为它会覆盖所有样式,而且没有其他方法可供使用。 [class]
和 [ngClass]
具有相同的行为,如果您必须经常执行上述操作,您可以编写一个名为 [addClass]
的自定义指令,它仅附加 CSS 样式。