我有以下指令,用于处理从应用它的元素开始的所有子元素的可见性/启用。
在ngAfterViewInit
中,该指令检索向 Web API 提供组件名称属性和记录的用户角色的元素的配置。之后,配置将应用于与配置中的行匹配的所有元素。
import {
Directive, Input,
ElementRef, AfterViewInit, ViewContainerRef, Renderer2, DoCheck
} from '@angular/core';
import { CompConfig } from '../model/comp-config';
import { ConfigService } from '../services/config.service';
@Directive({
selector: '[limsApplyConfig]'
})
export class ApplyConfigDirective implements AfterViewInit, DoCheck {
config: CompConfig[];
compName: string;
constructor(
private hostElement: ElementRef,
private cs: ConfigService,
private renderer: Renderer2
) { }
@Input() set limsApplyConfig(compName: string) {
this.compName = compName;
}
ngAfterViewInit(): void {
// start with everything hidden: when a config will be received
// elements can be enabled following configuration
this.renderer.addClass(this.hostElement.nativeElement, 'cfg-hidden');
this.cs.getConfig(this.compName).subscribe(c => {
this.renderer.removeClass(this.hostElement.nativeElement, 'cfg-hidden');
this.config = c;
this.config.forEach(cfg => {
if (this.hostElement.nativeElement.querySelectorAll) {
const inputCollection = this.hostElement.nativeElement.querySelectorAll('#' + cfg.ControlName);
inputCollection.forEach(n => {
// readonly is a property of inputs
if (n.readOnly !== undefined) {
n.readOnly = cfg.Disable;
}
// disabled is a property of buttons
if (n.disabled !== undefined) {
n.disabled = cfg.Disable;
}
if (cfg.Invisible) {
this.renderer.addClass(n, 'cfg-hidden');
}
});
}
});
});
}
ngDoCheck(): void {
if (this.config && this.config.length > 0) {
this.config.forEach(cfg => {
if (this.hostElement.nativeElement.querySelectorAll) {
const inputCollection = this.hostElement.nativeElement.querySelectorAll('#' + cfg.ControlName);
inputCollection.forEach(n => {
if (n.readOnly !== undefined) {
n.readOnly = cfg.Disable;
}
if (n.disabled !== undefined) {
n.disabled = cfg.Disable;
}
if (cfg.Invisible) {
this.renderer.addClass(n, 'cfg-hidden');
}
});
}
});
}
}
}
对于元素的启用/禁用状态,我很难使指令赢得组件的特定逻辑。配置永远不会改变,但按钮/输入的状态会改变。
换句话说,如果应该禁用一个按钮,我想禁用它并保持禁用状态,即使组件的逻辑会启用它。不幸的是,我做不到。我尝试添加ngDoCheck
生命周期钩子,但没有任何成功。
任何帮助将不胜感激
指令只计算一次,直到输入更改。如果您的组件正在更改指令的输入 [并且您的组件正在启用该按钮,但您仍然希望通过指令禁用它,请确保每次指令的输入更改时都执行您的订阅。如果我对您的问题的理解是正确的,那么让我们按如下方式更改代码 [请导入必要的类并原谅格式] -
import {
Directive, Input,
ElementRef, AfterViewInit, ViewContainerRef, Renderer2, DoCheck
} from '@angular/core';
import { CompConfig } from '../model/comp-config';
import { ConfigService } from '../services/config.service';
@Directive({
selector: '[limsApplyConfig]'
})
export class ApplyConfigDirective implements AfterViewInit, DoCheck {
config: CompConfig[];
compName: string;
compName$: BehaviorSubject<string>;
constructor(
private hostElement: ElementRef,
private cs: ConfigService,
private renderer: Renderer2
) {
this.compName$ = new BehaviorSubject<string>(null);
}
@Input() set limsApplyConfig(compName: string) {
this.compName$.next(compName);
}
ngAfterViewInit(): void {
// start with everything hidden: when a config will be received
// elements can be enabled following configuration
this.renderer.addClass(this.hostElement.nativeElement, 'cfg-hidden');
this.compName$
.pipe(
mergeMap(cn => this.cs.getConfig(cn)),
tap(config => {
this.config.forEach(cfg => {
if (this.hostElement.nativeElement.querySelectorAll) {
const inputCollection = this.hostElement.nativeElement.querySelectorAll('#'
+ cfg.ControlName);
inputCollection.forEach(n => {
// readonly is a property of inputs
if (n.readOnly !== undefined) {
n.readOnly = cfg.Disable;
}
// disabled is a property of buttons
if (n.disabled !== undefined) {
n.disabled = cfg.Disable;
}
if (cfg.Invisible) {
this.renderer.addClass(n, 'cfg-hidden');
}
});
}
});
})
).subscribe();
}
}