【问题标题】:Angular @Input set programmatically for 3rd party controlsAngular @Input 以编程方式为 3rd 方控件设置
【发布时间】:2021-08-20 04:04:55
【问题描述】:

我正在使用 PrimeNG 控件。我正在通过指令在各种输入控件上设置禁用属性,其中一些控件是 p-dropdown、p-listbox 和 p-calendar PrimeNG 控件。基本的输入、textarea 和 select 控件可以正常工作,但 PrimeNG 控件已禁用定义为 @Input,如下所示:

private _disabled: boolean;

@Input() get disabled(): boolean {
    return this._disabled;
};

指令的代码sn-p如下:

/*
** 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 3rd 方控件?我在想,在给定元素引用的情况下,我需要一种方法来实现禁用的 @Input 属性。

【问题讨论】:

  • 抱歉,您有什么问题?
  • 那么,如何在给定 ElementRef.nativeElement 的情况下禁用 PrimeNG 3rd 方控件?谢谢
  • 您现在可以禁用任何输入吗.. 或收到任何错误
  • 我可以禁用输入、选择和文本区域。我无法禁用 p-dropdown、p-listbox 和 p-calendar。

标签: angular typescript dom primeng


【解决方案1】:

基本上,我认为使用指令以编程方式禁用控件并不是一个好主意,我完全建议您使用旧输入来处理它。

但我可以针对您的情况提出以下解决方案:https://stackblitz.com/edit/angular-disable-prime-ng-elements

解决方案本身并不完美 - 但如果您不想使用 disabled 输入,这是一种权衡。

  1. 首先,创建一个名为PrimeNgComponentsChangeDetectorRefDirective 的指令,以获取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
    );
  }
}
  1. 然后,在您的禁用指令中实现以下属性和方法:
  @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 对此更改一无所知。

【讨论】:

  • 太棒了。不喜欢 setTimeout,将 hostComponent 改为 getter 并返回 getHostComponent。
  • 是的,setTimeout 只是为了检查解决方案是否有效
  • lint 对上面的 'p-checkbox, p-dropdown, p-listbox' 选择器不满意,声明 directive-selector 选择器应该用作属性 (angular.io/guide/styleguide#style-02-06)
  • 嘿,我刚刚实现了安全性并开始使用它,它不处理 div 标签内的 PrimeNG 控件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
相关资源
最近更新 更多