I have a form with input and select tags.
When all tags are invalid they should show a red left border.
That works only for input tags, but no select tags.
The invalid input-tag has these css classes applied during runtime:
class="form-control ng-pristine ng-invalid ng-touched"
The invalid select-tag has these css classes applied during runtime:
class="form-control ng-valid ng-touched ng-dirty"
As you can see on the screenshot the both dropdowns/select elements do not have the red/green left border added via this css:
.ng-valid[required], .ng-valid.required {
border-left: 5px solid #42A948; /* green */
}
.ng-invalid:not(form) {
border-left: 5px solid #a94442; /* red */
}
I should mention that the validation for the select-tags is a custom validation and its errors are retrieved from the schooylearForm
not from the schoolyearForm.bestGrade
property. Maybe that is the problem, that I still have to manually set the control state to invalid, that the ng-invalid classes is added to the select-tag???
HTML
<div class="form-group row">
<label class="col-xs-3 col-form-label" for="power">Beste Note für einen Test</label>
<div class="col-xs-3">
<select formControlName="bestGrade" class="form-control">
<option *ngFor="let t of allGrades" [ngValue]="t">{{t}}</option>
</select>
</div>
<div class="col-xs-6" *ngIf="schoolyearForm.controls.bestGrade.touched">
<div class="form-error form-control" *ngIf="schoolyearForm.hasError('equalGrades')">
Beste Note darf nicht gleich schlechteste Note sein.
</div>
</div>
</div>
Component
this.schoolyearForm = this.formBuilder.group({
name: [this.createSchoolyear.name, [Validators.minLength(3), Validators.required]],
endDate: [this.createSchoolyear.endDate, Validators.required],
startDate: [this.createSchoolyear.startDate, Validators.required],
bestGrade: [this.createSchoolyear.bestGrade],
worstGrade: [this.createSchoolyear.worstGrade,]
}, {validator: matchingGrades('bestGrade', 'worstGrade')});
Validator
export function matchingGrades(bestGrade: string, worstGrade: string) {
return (group: FormGroup): {[key: string]: any} => {
let bestGradeObject = group.controls[bestGrade];
let worstGradeObject = group.controls[worstGrade];
if (bestGradeObject.value == worstGradeObject.value) {
// bestGradeObject.markAsInvalid = true // DOES NOT EXIST !
return {
equalGrades: true
};
}
}
}
UPDATE
I ound out when I change this css:
.ng-invalid:not(form) {
border-left: 5px solid #a94442; /* red */
}
to
.ng-invalid {
border-left: 5px solid #a94442; /* red */
}
then indeed the whole form gets that red border when both select-tags has the same value selected.
Then I change my question to:
How can I make the equalGrades custom validation depended on both properties bestGrade/worstGrade and not on the whole.
UPDATE 2
I made it work with that code:
if (bestGradeObject.value == worstGradeObject.value)
{
bestGradeObject.setErrors({ "equalGrades": true });
worstGradeObject.setErrors({ "equalGrades": true });
return {
equalGrades: true
};
}
else
{
bestGradeObject.setErrors(null);
worstGradeObject.setErrors(null);
}
UPDATE 3
Now I used the code from user 'developer033'
which uses Validation on the FormControl level not FormGroup level.
Initially the one dropdown has NO red border set due to the level change which I do not like.
How can this be fixed?
P.S. Its a chicken egg problem, I can not now pass the worstGradeCtrl to the constructor of the bestGradeCtrl...