I'm working on a form with Angular Forms and I have hit a deadend where I want to add validation to a second input field only if the first is not empty.
Let's say I have two input fields: name and age. So when something is typed into name, only then age will be set to required. I'm using FormGroup and FormControl for my form and this is how the component file looks like now without validators for age:
class Component implements OnChanges {
@Input() name: string;
@Input() age: string;
form = new FormGroup({
name: new FormControl(''),
age: new FormControl('')
});
ngOnChanges(changes) {
if (changes.name?.currentValue !== changes.name?.previousValue) {
this.setName(changes.name.currentValue);
}
if (changes.age?.currentValue !== changes.age?.previousValue) {
this.setAge(changes.age.currentValue);
}
}
setName(name) {
this.form.patchValue({
name,
});
if (name) {
this.form.get('age').setValidators([
Validators.required,
this.form.get('age').validator
]);
}
}
setAge(age) {
this.form.patchValue({
age,
});
}
}
Here's the template:
<custom-input
label="Name"
placeholder="name"
name="name"
formControlName="name"
></custom-input>
<custom-input
label="Age"
placeholder="age"
name="age"
formControlName="age"
></custom-input>
CodePudding user response:
You can use the below method!
listen to change event of the form fields you want,then check if the field is filled, then we can toggle the required with the command setValidators
then after its updated we can ensure the form is in sync by running the updateValueAndValidity
which will revalidate the form!
ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import {
FormBuilder,
FormControl,
FormGroup,
Validators,
} from '@angular/forms';
import { Subscription } from 'rxjs';
import { pairwise, startWith } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit, OnDestroy {
name = 'Angular';
form: FormGroup;
subscription: Subscription;
constructor(private formBuilder: FormBuilder) {}
ngOnInit(): void {
this.form = this.formBuilder.group({
control1: [''],
control2: [''],
});
}
control1Change() {
const control1 = <FormControl>this.form.get('control1');
const control2 = <FormControl>this.form.get('control2');
if (control1.value) {
control2.setValidators([Validators.required]);
} else {
control2.setValidators(null);
}
control2.updateValueAndValidity();
}
control2Change() {
const control1 = <FormControl>this.form.get('control1');
const control2 = <FormControl>this.form.get('control2');
if (control2.value) {
control1.setValidators([Validators.required]);
} else {
control1.setValidators(null);
}
control1.updateValueAndValidity();
}
ngOnDestroy(): void {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}
HTML
<hello name="{{ name }}"></hello>
<form [formGroup]="form">
<div style="margin-bottom: 1rem">
<label for="control1">Make Field 2 required</label>
<input
id="control1"
type="text"
formControlName="control1"
(change)="control1Change()"
/>
<span
*ngIf="form.controls.control1.hasError('required')"
style="color: red; display: block; margin-top: 0.25rem;"
>Field 2 is required</span
>
</div>
<div style="margin-bottom: 1rem">
<label for="control2"> Field 2 </label>
<input
id="control2"
type="text"
formControlName="control2"
(change)="control2Change()"
/>
<span
*ngIf="form.controls.control2.hasError('required')"
style="color: red; display: block; margin-top: 0.25rem;"
>Field 2 is required</span
>
</div>
<div>
<button type="submit" [disabled]="!form.valid">
Only enabled when form is valid
</button>
</div>
</form>