简体   繁体   中英

Angular2 Reactive Forms Validation

I have a simple component that implements reactive forms and sets up 7 input fields which are select inputs.

I am trying to apply a validator on it to force at least one of them to contain a value.

Component:

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

When I submit my form an inspect the form itself, it keeps saying that its valid, even though none of the inputs have been filled out.

When I look at the individual form control values, they are displaying as null , verifying that not value has been stored.

Anything noticeable that I am doing wrong?

Update:

Not sure if this matters but a value of my input is an array:

在此处输入图片说明

I would think that this is still considered to be true when testing to see if it has a value?

Update 2: Here is a snippet of my HTML. This snippet is the same for each dropdown, just references a different function to populate it.

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

Update 3:

As requested, here is the full HTML template.

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

Update 4:

As a test, I commented out all of the validation logic and just returned return { validFilter: true }; expecting it to tell my form that its valid . However, this was not the case and the form is still invalid .

Seems like there may be an underlying issue somewhere else?

You can try this

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]
        });

This would make your form with a default values of ' ' with required validation. The reason why the validators are in array is because you can also add multiple validator like this

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

Hope this helps

So I could be wrong, but at first glance it looks like you have the validator mixed up. It should be the following:

/**
 * 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 };
    }
}

The way validators work is that a "valid" validator returns null, in other words: "I didn't find anything wrong". If it finds something it returns an object with a descriptively named property with a boolean value that further describes the state of the property, most likely "true". This is used to trigger different errors and inform the form of which error occured so you can apply different labels and error messages.

My code looks a bit different ... not sure if it would change things for you:

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;
    }
}
  • In the return statement, the return value is a string and a boolean, so I enclosed it in quotes.

  • I also used .get instead of .controls, but that should not matter.

I have a working example of a custom group validator here for reference if that helps: https://github.com/DeborahK/Angular2-ReactiveForms/tree/master/Demo-Final-Updated

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM