Reputation: 71
I have a form which changes its validation based on some value from the dropdown. If college A is selected then min percentage required in 60, if college B is selected then min percentage drops down to 55. Although I have figured out a way to get the min error in the template in so that I didn't have to hard code the percentage value in my template. Although I am not sure if this is the correct way or not.
<div formGroupName="marks">
<div class="form-group">
<label for="email" class="col-lg-3 control-label">Semester 1</label>
<div class="col-lg-3">
<input autocomplete="off"
#sem1
type="text"
min="0"
max="99"
maxlength="1"
maxlength="2"
class="form-control"
id="email"
placeholder="Sem 1 (%)"
(keypress)="onlyNumberKey($event)"
formControlName="sem1">
<span *ngIf="registrationForm.controls['marks'].controls['sem1'].hasError('required') &&
registrationForm.controls['marks'].controls['sem1'].touched"
class="text-danger">
Sem 1 percentage required
</span>
<span *ngIf="registrationForm.controls['marks'].controls['sem1'].hasError('min') ||
registrationForm.controls['marks'].controls['sem1'].hasError('max') ||
registrationForm.controls['marks'].controls['sem1'].hasError('minlength')||
registrationForm.controls['marks'].controls['sem1'].hasError('maxlength') &&
registrationForm.controls['marks'].controls['sem1'].touched"
class="text-danger">
Percenatge must be {{ registrationForm.get('marks.sem1')._errors.min.min }} and above.
</span>
</div>
</div>
</div>
Component
registrationForm = new FormGroup({
college: new FormControl('', [
Validators.required, dropDrownValidator
]),
marks: new FormGroup({
sem1: new FormControl('',
[
Validators.required,
Validators.min(60),
Validators.max(99),
Validators.minLength(1),
Validators.maxLength(2)
]
)
})
});
Upvotes: 6
Views: 18413
Reputation: 24874
To achieve what you want, you have to watch the changes in your college
control.
You can do this using (change)
in template:
<select formControlName="college" (change)="handleChange($event.target.value)">
...
</select>
or even using valueChanges
in component:
this.registrationForm.get('college').valueChanges.subscribe(college => this.handleChange(college));
And in your function
, based on what college user selects, you can set the min value to your validator using AbstractControl#setValidators
+ AbstractControl#updateValueAndValidity
(to apply ), as below:
handleChange(selectedCollege: string): void {
const min = selectedCollege === 'CollegeA' ? 60 : 55;
const control = this.registrationForm.get('marks.sem1');
control.setValidators([Validators.required, customMin(min)]);
control.updateValueAndValidity();
}
Tips:
1 - Since, you're using model-driven forms you shouldn't put validations in your HTML, keep it clean and put everything in component.
2 - You can use FormBuilder
in order to simplify the construction of form
(see the demo at the bottom).
3 - You should never access private properties like this:
{{ registrationForm.get('marks.sem1')._errors.min.min }}
Just use errors
instead of _errors
if you need to.
4 - You can simplify even more your markup:
Instead of:
<span *ngIf="registrationForm.controls['marks'].controls['sem1'].hasError('required') &&
registrationForm.controls['marks'].controls['sem1'].touched"
class="text-danger">
Sem 1 percentage required
</span>
<span *ngIf="registrationForm.controls['marks'].controls['sem1'].hasError('min') ||
registrationForm.controls['marks'].controls['sem1'].hasError('max') ||
registrationForm.controls['marks'].controls['sem1'].hasError('minlength')||
registrationForm.controls['marks'].controls['sem1'].hasError('maxlength') &&
registrationForm.controls['marks'].controls['sem1'].touched"
class="text-danger">
Percenatge must be {{ registrationForm.get('marks.sem1')._errors.min.min }} and above.
</span>
You can have:
<div class="text-danger" *ngIf="registrationForm.get('marks.sem1').touched">
<span *ngIf="registrationForm.hasError('required', 'marks.sem1')">
Sem 1 percentage required
</span>
<span *ngIf="registrationForm.getError('customMin', 'marks.sem1') as error">
Percentage must be greater than or equal to {{ error.min }}.
</span>
</div>
Upvotes: 7