Angular @Input 以编程方式为第 3 方控件设置
Angular @Input set programmatically for 3rd party controls
我正在使用 PrimeNG 控件。我通过指令在各种输入控件上设置禁用属性,其中一些控件是 p-dropdown、p-listbox 和 p-calendar PrimeNG 控件。基本输入、textarea 和 select 控件可以正常工作,但 PrimeNG 控件已禁用定义为 @Input,如下所示:
private _disabled: boolean;
@Input() get disabled(): boolean {
return this._disabled;
};
指令代码片段如下:
/*
** find all inputs and disable them.
*/
disableElements( el: ElementRef ): void {
const controls = el.nativeElement.querySelectorAll( 'input, select, textarea, p-dropdown, p-listbox, p-checkbox' );
controls.forEach( (elmt: any) => {
this.disableElement( elmt );
});
}
/*
** disable an input element.
*/
disableElement( elmt: any ): void {
if( elmt.localName.substr(0,2) === 'p-' ) {
this._renderer.setProperty(elmt, 'disabled', 'true');
} else {
if(!elmt.hasAttribute('disabled')) {
this._renderer.setAttribute(elmt, 'disabled', 'true');
}
}
}
那么,如何在给定 ElementRef.nativeElement 的情况下禁用 PrimeNG 第三方控件?我在想,我需要一种方法来实现禁用 @Input 属性 给定元素引用。
基本上我不认为使用指令以编程方式禁用控件是个好主意,我完全建议您改为使用良好的旧输入来处理它。
但我可以针对您的情况提出以下解决方案:https://stackblitz.com/edit/angular-disable-prime-ng-elements
解决方案本身并不完美 - 但如果您不想使用 disabled
输入,这是一种权衡。
- 首先,创建一个名为
PrimeNgComponentsChangeDetectorRefDirective
的指令来获取 public 版本的 primeng 组件的变更检测器来更新它们的视图。您应该手动包含所有要处理的 primeng 组件。这里的技巧是使用相同的选择器来自动匹配 primeng 组件。
@Directive({
selector: 'p-checkbox, p-dropdown, p-listbox'
})
export class PrimeNgComponentsChangeDetectorRefDirective {
public hostComponent: Checkbox | Dropdown | Listbox;
constructor(
public cdr: ChangeDetectorRef,
@Optional() private checkbox: Checkbox,
@Optional() private dropdown: Dropdown,
@Optional() private listbox: Listbox
) {}
ngAfterViewInit() {
this.hostComponent = this.getHostComponent();
}
private getHostComponent() {
return [this.checkbox, this.dropdown, this.listbox].find(
component => !!component
);
}
}
- 然后,在您的禁用指令中实现以下属性和方法:
@ContentChildren(PrimeNgComponentsChangeDetectorRefDirective)
private componentsQuery: QueryList<
PrimeNgComponentsChangeDetectorRefDirective
>;
disablePrimeNgComponents() {
const components = this.componentsQuery.toArray();
components.forEach(component => {
component.hostComponent.disabled = true;
component.cdr.detectChanges();
});
}
我们需要手动 detectChanges
,因为我们已经以编程方式更改了 disabled
属性,而 angular 对此更改一无所知。
我正在使用 PrimeNG 控件。我通过指令在各种输入控件上设置禁用属性,其中一些控件是 p-dropdown、p-listbox 和 p-calendar PrimeNG 控件。基本输入、textarea 和 select 控件可以正常工作,但 PrimeNG 控件已禁用定义为 @Input,如下所示:
private _disabled: boolean;
@Input() get disabled(): boolean {
return this._disabled;
};
指令代码片段如下:
/*
** find all inputs and disable them.
*/
disableElements( el: ElementRef ): void {
const controls = el.nativeElement.querySelectorAll( 'input, select, textarea, p-dropdown, p-listbox, p-checkbox' );
controls.forEach( (elmt: any) => {
this.disableElement( elmt );
});
}
/*
** disable an input element.
*/
disableElement( elmt: any ): void {
if( elmt.localName.substr(0,2) === 'p-' ) {
this._renderer.setProperty(elmt, 'disabled', 'true');
} else {
if(!elmt.hasAttribute('disabled')) {
this._renderer.setAttribute(elmt, 'disabled', 'true');
}
}
}
那么,如何在给定 ElementRef.nativeElement 的情况下禁用 PrimeNG 第三方控件?我在想,我需要一种方法来实现禁用 @Input 属性 给定元素引用。
基本上我不认为使用指令以编程方式禁用控件是个好主意,我完全建议您改为使用良好的旧输入来处理它。
但我可以针对您的情况提出以下解决方案:https://stackblitz.com/edit/angular-disable-prime-ng-elements
解决方案本身并不完美 - 但如果您不想使用 disabled
输入,这是一种权衡。
- 首先,创建一个名为
PrimeNgComponentsChangeDetectorRefDirective
的指令来获取 public 版本的 primeng 组件的变更检测器来更新它们的视图。您应该手动包含所有要处理的 primeng 组件。这里的技巧是使用相同的选择器来自动匹配 primeng 组件。
@Directive({
selector: 'p-checkbox, p-dropdown, p-listbox'
})
export class PrimeNgComponentsChangeDetectorRefDirective {
public hostComponent: Checkbox | Dropdown | Listbox;
constructor(
public cdr: ChangeDetectorRef,
@Optional() private checkbox: Checkbox,
@Optional() private dropdown: Dropdown,
@Optional() private listbox: Listbox
) {}
ngAfterViewInit() {
this.hostComponent = this.getHostComponent();
}
private getHostComponent() {
return [this.checkbox, this.dropdown, this.listbox].find(
component => !!component
);
}
}
- 然后,在您的禁用指令中实现以下属性和方法:
@ContentChildren(PrimeNgComponentsChangeDetectorRefDirective)
private componentsQuery: QueryList<
PrimeNgComponentsChangeDetectorRefDirective
>;
disablePrimeNgComponents() {
const components = this.componentsQuery.toArray();
components.forEach(component => {
component.hostComponent.disabled = true;
component.cdr.detectChanges();
});
}
我们需要手动 detectChanges
,因为我们已经以编程方式更改了 disabled
属性,而 angular 对此更改一无所知。