Angular2反应表单验证

时间:2017-07-24 22:00:13

标签: angular typescript angular-reactive-forms

我有一个简单的组件,它实现了反应形式,并设置了7个输入字段select输入。

我正在尝试在其上应用验证器以强制其中至少一个包含值。

组件:

renderForm() {
        this.importForm = this.fb.group({
            costCenter: [],
            area: [],
            silo: [],
            department: [],
            location: [],
            segment: [],
            role: []
        },
            {
                validator: (formGroup: FormGroup) => {
                    return this.validateFilter(formGroup);
                }
            });
    }

    /**
     * Checks to see that at least one of the filter
     * options have been filled out prior to searching
     * for employees.
     *
     * @param formGroup
     */
    validateFilter(formgroup: FormGroup) {
        if (formgroup.controls["costCenter"].value ||
            formgroup.controls["area"].value ||
            formgroup.controls["silo"].value ||
            formgroup.controls["department"].value ||
            formgroup.controls["location"].value ||
            formgroup.controls["segment"].value ||
            formgroup.controls["role"].value
        ) {
            return { validateFilter: true };
        } else {
            return null;
        }
    }

当我提交表单时,检查form本身,它一直说它有效,即使没有填写任何输入。

当我查看单个表单控件值时,它们显示为null,验证没有存储值。

有什么迹象表明我做错了吗?

更新

不确定这是否重要,但我的输入值是一个数组:

enter image description here

我认为在测试它是否有值时,仍然认为这是true

更新2: 这是我的HTML片段。每个下拉列表的代码段相同,只是引用一个不同的函数来填充它。

<tr>
                <td class="col-md-2 strong">Area</td>
                <td>
                    <div class="form-group">
                        <ng-select formControlName="area" [allowClear]="true" [multiple]="true" [items]="getAreas()" placeholder="Select one or more Areas">
                        </ng-select>
                    </div>
                </td>
            </tr>

更新3:

根据要求,这是完整的HTML模板。

<tbody>
            <tr>
                <td class="col-md-2 strong">Cost Center</td>
                <td>
                    <div class="form-group">
                       <ng-select formControlName="costCenter" [allowClear]="true" [multiple]="true" [items]="getCostCenters()" placeholder="Select one or more Cost Centers">
                        </ng-select>
                    </div>
                </td>
            </tr>
            <tr>
                <td class="col-md-2 strong">Area</td>
                <td>
                    <div class="form-group">
                        <ng-select formControlName="area" name="area" [allowClear]="true" [multiple]="true" [items]="getAreas()" placeholder="Select one or more Areas">
                        </ng-select>
                    </div>
                </td>
            </tr>
            <tr>
                <td class="col-md-2 strong">Silo</td>
                <td>
                    <div class="form-group">
                        <ng-select formControlName="silo" name="silo" [allowClear]="true" [multiple]="true" [items]="getSilos()" placeholder="Select one or more Silos">
                        </ng-select>
                    </div>
                </td>
            </tr>
            <tr>
                <td class="col-md-2 strong">Department</td>
                <td>
                    <div class="form-group">
                        <ng-select formControlName="department" name="department" [allowClear]="true" [multiple]="true" [items]="getDepartments()" placeholder="Select one or more Departments">
                        </ng-select>
                    </div>
                </td>
            </tr>
            <tr>
                <td class="col-md-2 strong">Location</td>
                <td>
                    <div class="form-group">
                        <ng-select formControlName="location" name="location" [allowClear]="true" [multiple]="true" [items]="getLocations()" placeholder="Select one or more Locations">
                        </ng-select>
                    </div>
                </td>
            </tr>
            <tr>
                <td class="col-md-2 strong">Segment</td>
                <td>
                    <div class="form-group">
                        <ng-select formControlName="segment" name="segment" [allowClear]="true" [multiple]="true" [items]="getSegments()" placeholder="Select one or more Segments">
                        </ng-select>
                    </div>
                </td>
            </tr>
            <tr>
                <td class="col-md-2 strong">Role</td>
                <td>
                    <div class="form-group">
                        <ng-select formControlName="role" name="role" [allowClear]="true" [multiple]="true" [items]="getRoles()" placeholder="Select one or more Roles">
                        </ng-select>
                    </div>
                </td>
            </tr>
        </tbody>

更新4:

作为测试,我注释掉了所有验证逻辑,并且刚刚返回return { validFilter: true };,希望它告诉我的表单valid。但是,情况并非如此,表单仍为invalid

似乎在其他地方可能存在潜在问题?

3 个答案:

答案 0 :(得分:1)

你可以试试这个

this.importForm = this.fb.group({
            costCenter: ['', [Validators.required],
            area:  ['', [Validators.required],
            silo: ['', [Validators.required],
            department: ['', [Validators.required],
            location: ['', [Validators.required],
            segment: ['', [Validators.required],
            role:  ['', [Validators.required]
        });

这会使您的表单的默认值为'',并且需要验证。验证器在数组中的原因是因为您还可以添加多个这样的验证器

 department: ['', [Validators.required,  Validators.minLength(3)]],

希望这有帮助

答案 1 :(得分:1)

所以我可能错了,但乍一看,看起来你的验证器已经混淆了。它应该如下:

/**
 * Checks to see that at least one of the filter
 * options have been filled out prior to searching
 * for employees.
 *
 * @param formGroup
 */
validateFilter(formgroup: FormGroup) {
    if (formgroup.controls["costCenter"].value ||
        formgroup.controls["area"].value ||
        formgroup.controls["silo"].value ||
        formgroup.controls["department"].value ||
        formgroup.controls["location"].value ||
        formgroup.controls["segment"].value ||
        formgroup.controls["role"].value
    ) {
        return null
    } else {
        return { noFilterOptionsSet: true };
    }
}

验证器的工作方式是“有效”验证器返回null,换句话说:“我没有发现任何错误”。如果它找到了某个东西,它返回一个具有描述性命名属性的对象,其中一个布尔值进一步描述了该属性的状态,很可能是“真”。这用于触发不同的错误并告知发生错误的形式,以便您可以应用不同的标签和错误消息。

答案 2 :(得分:0)

我的代码看起来有点不同......不确定它是否会改变你的想法:

validateFilter(formgroup: FormGroup) {
    if (formgroup.get("costCenter").value ||
        formgroup.get("area").value ||
        formgroup.get("silo").value ||
        formgroup.get("department").value ||
        formgroup.get("location").value ||
        formgroup.get("segment").value ||
        formgroup.get("role").value
    ) {
        return { 'validateFilter': true };
    } else {
        return null;
    }
}
  • 在return语句中,返回值是一个字符串和一个布尔值,因此我将其括在引号中。

  • 我也使用.get代替.controls,但这无关紧要。

我在这里有一个自定义组验证器的工作示例,以供参考,如果有帮助:https://github.com/DeborahK/Angular2-ReactiveForms/tree/master/Demo-Final-Updated