首页 文章

如何在Angular2 Typescript中更改HTML元素readonly和required属性?

提问于
浏览
22

对于我的一些组件,我想改变输入字段readonly和来回的必需属性 .

我已经得到了一个运行的代码,改变两者的需求,但问题是,它为只读,但似乎并没有被工作需要的:尽管元素属性更改所需Angular2仍然认为fieldCtrl是有效的 .

这是我的傻瓜,我在这里说明了这个问题:https://plnkr.co/edit/Yq2RDzUJjLPgReIgSBAO?p=preview

//our root app component
import {Component} from 'angular2/core'

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
    <form #f="ngForm">
      <button type="button" (click)="toggleReadOnly()">Change readonly!</button>
      <button type="button" (click)="toggleRequired()">Change required!</button>
      <input id="field" [(ngModel)]="field" ngControl="fieldCtrl" #fieldCtrl="ngForm"/>
      {{fieldCtrl.valid}}
    </form>
    </div>
  `,
  directives: []
})
export class App {
  constructor() {
    this.name = 'Angular2'
  }

  toggleRequired(){
    this.isRequired = !this.isRequired;
    var fieldElement = <HTMLInputElement>document.getElementById('field');
    if (this.isRequired){
      fieldElement.required = true;
      this.field = "it's required now";
    }
    else{
      fieldElement.required = false;
      this.field = "can leave it blank";
    }
  }

  toggleReadOnly(){
    this.isReadOnly = !this.isReadOnly;
    var fieldElement = <HTMLInputElement>document.getElementById('field');
    if (this.isReadOnly){
      fieldElement.readOnly = true;
      this.field = "it's readonly now";
    }
    else{
      fieldElement.readOnly = false;
      this.field = "feel free to edit";
    }
  }

  private isReadOnly:boolean=false;

  private field:string = "feel free to edit";

  private isRequired:boolean=false;

}

更新:尝试建议的方法

[required]="isRequired" [readonly]="isReadOnly"

它就像readonly的魅力一样,并且对于required = true,但我不能再关闭所需的属性 - 它显示空字段无效,尽管不再需要 .

更新的plunker:https://plnkr.co/edit/6LvMqFzXHaLlV8fHbdOE

UPDATE2:尝试建议的方法

[required]="isRequired ? true : null"

它确实逐个元素地添加/删除所需的属性,但是对于不需要的空字段,字段控制器的有效属性显示为false .

在Angular2 Typescript中更改所需属性的正确方法是什么?

3 回答

  • 31

    对于要删除的绑定属性,需要将它们设置为null . 有一个讨论要改变它以删除,但它被拒绝,至少现在 .

    [required]="isRequired ? '' : null"
    

    要么

    [required]="isRequired ? 'required' : null"
    

    您的Plunker会因为 ngControl 周围缺少 [] 而产生错误 .

    另请参阅此Plunker以获取工作示例

    另见Deilan的评论如下 .

  • 5

    您似乎已经有了添加/删除readonly属性的答案 . 对于required属性,我建议创建一个服务来跟踪验证器的启用/禁用状态,然后在绑定到验证控件时利用该服务 .

    状态验证器

    该类负责跟踪验证器及其启用/禁用状态 .

    export class StateValidator {
        public enabled: boolean = true;
        validator: (control: Control) => { [key: string]: boolean };
        constructor(validator: (control: Control) => 
            { [key: string]: boolean }, enabled: boolean) {
            this.enabled = enabled;
            this.validator = validator;
    
        }
    
        enable() {
            this.enabled = true;
        }
        disable() {
            this.enabled = false;
        }
        toggle() {
            this.enabled = !this.enabled;
        }
        get() {
            return (control: Control) => {
                if (this.enabled)
                    return this.validator(control);
                return null;
            }
        }
    }
    

    它具有启用,禁用或切换验证器的方法;也是一个 get 方法返回一个新的验证功能,调用将调用底层的验证功能是否启用了验证,或者未启用验证时返回null时 .

    验证服务

    此类是一个单例服务,负责按键注册验证器,以及支持基于该密钥启用,禁用或切换验证器的方法 .

    export class ValidationService {
        validators: { [key: string]: StateValidator } = {};
        register(key: string, validator: Function): Function {
            var stateValidator = new StateValidator(<(control: Control) => { [key: string]: boolean }>validator, true);
            this.validators[key] = stateValidator;
            return stateValidator.get();
        }
        enable(key: string) {
            this.validators[key].enable();
        }
        disable(key: string) {
            this.validators[key].disable();
        }
        toggle(key: string) {
            this.validators[key].toggle();
        }
        list() {
            var l = [];
            for (var key in this.validators) {
                if (this.validators.hasOwnProperty(key)) {
                    l.push({ key: key, value: this.validators[key].enabled });
                }
            }
            return l;
        }
    }
    

    该服务还拥有返回键/值对的列表,其中的关键代表注册验证密钥的 list 功能,并且该值是一个布尔值的指标,代表了验证器的启用状态 .

    组件

    要使用 ValidationService ,请在引导期间使用根注入器注册服务:

    bootstrap(AppComponent, [ValidationService]);
    

    或者使用组件级注入器注册服务:

    @Component({
      selector: 'app',
      providers: [ValidationService],
      ...
    })
    

    然后在组件的构造函数中注入服务:

    export class AppComponent {
        form: ControlGroup;
        constructor(public validationService:ValidationService) {
          ...
        }
    }
    

    接下来,像往常一样绑定到验证控件,除了使用 ValidationService 注册并返回状态验证器:

    new Control('', validationService.register('required', Validators.required));
    

    此解决方案的一大优点是,您可以轻松地将状态验证器与其他内置或自定义验证器进行组合和混合:

    this.form = new ControlGroup({
        name: new Control('hello',
            Validators.compose([
                validationService.register('required', Validators.required),
                validationService.register('minlength', Validators.minLength(4)),
                Validators.maxLength(10)]))
    
    });
    

    切换验证器

    使用该服务切换验证器的状态:

    validationService.toggle('required');
    

    下面是一个如何绑定到表中的状态验证器列表,并将toggle函数连接到按钮单击事件的示例:

    <table>
      <tr>
         <td>Validator</td>
         <td>Is Enabled?</td>
         <td></td>
      </tr>
      <tr *ngFor="#v of validationService.list()">
         <td>{{v.key}}</td>
         <td>{{v.value }}</td>
         <td><button (click)="validationService.toggle(v.key)">Toggle</button></td>
      </tr>
    </table>
    

    Demo Plnkr

    enter image description here

  • 2

    我使用的替代解决方案:

    import {Directive, ElementRef, Input} from '@angular/core';
    
    @Directive({
        selector: '[symToggleRequired]'
    })
    export class ToggleRequiredDirective {
        @Input() public set symToggleRequired(condition: boolean) {
            if (condition) {
                (<HTMLElement>this.element.nativeElement).setAttribute('required', 'true');
            } else {
                (<HTMLElement>this.element.nativeElement).removeAttribute("required");
            }
        } 
    
        constructor(
            private element: ElementRef
        ) { } 
    }
    

    在html元素上使用此指令可删除或添加必需属性:

    <input [symToggleRequired]='FlagPropertyOfYourComponent'>
    

相关问题