【问题标题】:Make all form controls read-only in template-based form在基于模板的表单中将所有表单控件设为只读
【发布时间】:2017-11-01 20:39:24
【问题描述】:

我们有一个基于模板的表单,它使用各种 Angular Material 控件(matInput、mat-select 等)。我们想为某些用户创建一个“只读”类型的视图。我的直接想法是简单地检查用户的权限,然后遍历所有表单控件并在需要时将它们设置为禁用。

这似乎适用于文本输入类型控件,但不适用于选择和复选框。另外,这会使我们不需要的控件变灰。

关于如何最好地实现这一点的任何想法?也许以某种方式禁用表单中的键盘和鼠标输入可能是我们想要的,但我不知道该怎么做。

【问题讨论】:

  • 不要尝试禁用输入。你有写作的想法,但你需要做更多的工作才能使选择和收音机工作。尝试*ngIf 并根据表单的状态呈现不同的控件。至于外观如何,可以调整。
  • 问题是我们的表单非常复杂,可以有无数的属性。为每个控件手动构建条件是不现实的。我需要一种通用方法,可以应用于具有任意数量的控件和控件类型的任何表单。
  • 我的建议是将每个控件包装在一个公开更高级别 API 的组件中。例如,您可以公开 readonly 属性、model 属性和 input-type 属性。
  • 也就是说,我建议你看看像 ng2formly 这样的东西。
  • @AluanHaddad 你说'不要试图禁用输入'。这是为什么呢?

标签: forms angular


【解决方案1】:

我认为这是可能的,但您必须检查所有控件类型,例如 MatInput 公开 readonly 属性,它允许我们创建简单的指令,该指令将切换整个表单的 readonly 状态:

import {Directive, ContentChildren, QueryList, AfterContentInit, Input} from '@angular/core';
import {NgModel} from '@angular/forms';

@Directive({
    selector: 'form[readonly]'
})
export class FormReadonlyDirective implements AfterContentInit
{
    @ContentChildren(NgModel)
    public inputs:QueryList<NgModel>;

    private controls:any[];

    private _readonly:boolean = false;

    public ngAfterContentInit():void
    {
        this.controls = this.getControls();

        this.inputs.changes.subscribe(() =>
        {
            this.setReadonly(this.readonly);
        });

        this.setReadonly(this.readonly);
    }

    @Input()
    public get readonly():boolean
    {
        return this._readonly;
    }

    public set readonly(value:boolean)
    {
        this._readonly = value != null && value !== false && `${value}` !== 'false';
        this.setReadonly(value);
    }

    private setReadonly(value:boolean):void
    {
        if(this.controls != null)
        {
            this.controls.forEach(control =>
            {
                //todo: check
                control.readonly = value;
            });
        }
    }

    private getControls():any[]
    {
        return this.inputs.map(control => control.valueAccessor);
    }
}

未经测试,但你明白了。

【讨论】:

  • 感谢您的回复。我现在意识到的问题是,我们的表单本身就是一个包含 的组件,表单组件的使用者然后在控件中扑通一声。但理论上你可能有嵌套的形式。我需要以某种方式将父表单的禁用状态传达给其各自的孩子。
  • 不幸的是,ContentChildren 可能不适用于ng-content,因此您将不得不使用解决方法...
猜你喜欢
  • 2011-04-06
  • 1970-01-01
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
  • 2012-07-29
  • 2013-03-30
相关资源
最近更新 更多