如何更改Angular2 Typescript中的HTML元素只读和必需属性?

如何更改Angular2 Typescript中的HTML元素只读和必需属性?,typescript,angular,Typescript,Angular,对于我的一些组件,我想前后更改输入字段readonly和required属性 我已经设法得到了一个运行的代码,可以根据需要更改这两个代码,但问题是它只适用于readonly,而不适用于required:尽管元素属性更改为required Angular2,但它仍然认为fieldCtrl是有效的 这是我的plunker,我在这里说明了这个问题: 对于readonly和required=true,它就像一个符咒,但是我不能再关闭required属性了——它显示空字段是无效的,尽管不再是必需的 更新的

对于我的一些组件,我想前后更改输入字段readonly和required属性

我已经设法得到了一个运行的代码,可以根据需要更改这两个代码,但问题是它只适用于readonly,而不适用于required:尽管元素属性更改为required Angular2,但它仍然认为fieldCtrl是有效的

这是我的plunker,我在这里说明了这个问题:

对于readonly和required=true,它就像一个符咒,但是我不能再关闭required属性了——它显示空字段是无效的,尽管不再是必需的

更新的plunker:

更新2: 尝试建议的方法

[required]="isRequired ? true : null"
它确实按需从元素中添加/删除必需属性,但对于不需要的空字段,field controller的valid属性显示为false


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

要删除绑定属性,需要将其设置为null。曾经有一次讨论将其更改为在false上删除,但被拒绝,至少现在是这样

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

由于缺少
ngControl
周围的
[]
,您的Plunker会产生错误

另请参见此以了解工作示例


另请参见下面Deilan的评论。

似乎您已经有了添加/删除只读属性的答案。对于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;
    }
}
或向组件级注入器注册服务:

@Component({
  selector: 'app',
  providers: [ValidationService],
  ...
})
然后将服务注入组件的构造函数中:

export class AppComponent {
    form: ControlGroup;
    constructor(public validationService:ValidationService) {
      ...
    }
}
接下来,像平常一样绑定到验证控件,除了使用
ValidationService
注册并返回状态验证程序外:

new Control('', validationService.register('required', Validators.required));
validationService.toggle('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)]))

});
切换验证器 使用该服务切换验证程序的状态:

new Control('', validationService.register('required', Validators.required));
validationService.toggle('required');
下面是一个示例,说明如何绑定到表中的状态验证器列表,并将切换函数连接到按钮单击事件:

<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>

验证器
是否已启用?
{{v.key}}
{{v.value}}
切换


我使用的替代解决方案:

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
    ) { } 
}
import{Directive,ElementRef,Input}来自'@angular/core';
@指示({
选择器:“[symToggleRequired]”
})
导出类切换RequiredDirective{
@Input()公共集symToggleRequired(条件:布尔值){
如果(条件){
setAttribute('required','true');
}否则{
移除属性(“必需”);
}
} 
建造师(
私有元素:ElementRef
) { } 
}
对html元素使用此指令可删除或添加所需的属性:

<input [symToggleRequired]='FlagPropertyOfYourComponent'>


当然,您不应该亲自进入DOM。你试过
[readonly]=readonly
?现在试过了,事实上就是这么简单:[required]=“isRequired”[readonly]=“isReadOnly”。事实上,现在我遇到了一个问题,我无法再关闭“required”。更新了我的问题。我要提到的是,您必须能够删除必需的属性,才能使其不被要求,因为
required=“false”
并不意味着它将不被要求,哦,我讨厌必须存在的属性/缺席很奇怪,残疾人应该为残疾人工作,这也是这些属性之一。您能在plunkr或JSFIDLE上创建一个实例吗?请参阅我更新了我的答案(另请参阅带有工作示例的Plunker链接)。您是champ。你有鹰眼+1确实删除了Required属性,但删除后fieldCtrl.valid仍然为空字段提供false。知道为什么吗?
[required]=“isRequired?”:null“
最适合我,因为如果条件为
true
,没有任何无效值,它会将
required
属性应用于DOM元素,如果条件为
false
@Deilan right,当
isRequired==true
时,使用什么值并不重要
null
删除该属性,任何其他值都会保留该属性。刚刚注意到我很好奇的plunker示例(angular2模板)中的语法技巧:“!name?.errors?.required”。请您评论一下,问号代表什么?@AndrisKrauze它们可以让您安全地访问可能为null或未定义的对象的属性。此帖子提供了更多信息:
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
    ) { } 
}
<input [symToggleRequired]='FlagPropertyOfYourComponent'>