Angular 2: Form valid返回false,直到所有字段都被填充



我正在使用响应式表单。

我有一个提交按钮,它应该被禁用,直到表单有效:

<button type="submit" [disabled]="!_searchForm.valid && !_searchForm.pristine">Submit</button>

我的字段可以使用bool开关:

showName: boolean = true;
showPhone: boolean = true;
showCellphone: boolean = true;

这是我的验证规则:

this._searchForm = this._formBuilder.group({
    name: [{value: '', disabled: !this.showName}, Validators.compose([Validators.minLength(3), Validators.maxLength(50), Validators.pattern('^[a-zA-Z]+$')])],
    phone: [{value: '', disabled: !this.showPhone}, Validators.compose([Validators.minLength(3), Validators.maxLength(50), Validators.pattern('^[0-9-]+$')])],
    cellphone: [{value: '', disabled: !this.showCellphone}, Validators.compose([Validators.minLength(3), Validators.maxLength(50), Validators.pattern('^[0-9]+$')])]
});

最后,每个字段在HTML中的显示方式如下:

<div class="form-group" [ngClass]="{'has-danger': _searchForm.controls.name.errors && !_searchForm.controls.name.pristine}">
<label for="name">Name:</label>
<div class="input-group">
    <span class="input-group-addon">
        <div class="onofwrapper">
            <div class="onoffswitch">
                <input id="toggleName" type="checkbox" class="onoffswitch-checkbox" (click)='toggleName()' [checked]="showName">
                <label class="onoffswitch-label" for="toggleName"></label>
            </div>
        </div>
    </span>
    <input type="text" formControlName="name" class="form-control" [ngClass]="{'form-control-danger': _searchForm.controls.name.errors && !_searchForm.controls.name.pristine}" autocomplete="off" spellcheck="false">
</div>
<div *ngIf="_searchForm.controls.name.errors && !_searchForm.controls.name.pristine" class="form-control-feedback">Error message</div>

如果我不触摸表单,我可以提交,所以pristine似乎工作。

问题是,我不能只在一个字段中输入文本并提交。如果我在一个字段中输入文本,我必须在所有字段中输入文本才能提交,否则即使我没有在所有字段上使用Validators.required, _searchForm.valid也不会返回true。

我已经验证了每个输入"发送自己的值",通过删除[disabled="!_searchForm.valid"行,然后只是在我的提交函数中倾销值,如下所示:

console.log('Name: ' + this._searchForm.value.name);
console.log('Phone: ' + this._searchForm.value.phone);
console.log('Cellphone: ' + this._searchForm.value.cellphone);

我做错了什么?为什么.valid需要表单中的所有字段?

如果您禁用或启用输入,那么,您需要一个函数:

enableDisableInput(inputName: string): void {
    if(!this._searchForm.controls[inputName].disabled) {
        this._searchForm.controls[inputName].clearValidators();
        this._searchForm.controls[inputName].disable();
    } else {
    this._searchForm.controls[inputName].setValidators(Validators.compose([Validators.minLength(3), Validators.maxLength(50), Validators.pattern('^[0-9]+$')])]);
    }
    this._searchForm.controls[inputName].updateValueAndValidity();
}

调用<input id="toggleName" type="checkbox" class="onoffswitch-checkbox" (click)='enableDisableInput("name")' [checked]="showName">

响应式表单构建和验证的方式意味着你必须手动清除和添加验证,即使是在禁用的项目上(可能有计划改变这一点,因为它在angular github上并不罕见)。这是一种面向代码和驱动的表单方式,目前需要这样对待。

如果输入具有未满足的最小长度,则是否需要输入是没有意义的。参考文献https://github.com/angular/angular/pull/11450,最近包含在Angular 2.0.2中https://github.com/angular/angular/blob/master/CHANGELOG.md

对于表单驱动,看起来他们在2.1.0中有一个修正,这些字段是可选的模式和最小长度,但我不知道这是否也在响应式表单。

原来这是input type="number"的问题。包含电话和手机值的字段应该只包含数字,因此除了Validators.pattern('^[0-9-]+$')验证之外,我还为它们提供了数字的输入类型。

一旦变成文本,一切都像预期的那样工作。

我在使用Angular响应式表单时也遇到了同样的问题。我基于一些逻辑禁用和启用了表单控件。结果是我禁用了表单控件,但没有启用,所以我得到了一个表单。为false有效。显然,在Angular的响应式表单中,禁用字段的表单是无效的,而且文档中也没有提到这种默认行为。

最新更新