Reputation: 91
i am making a custom validator in Angular. the purpose of the validator is that it makes certain fields required when a checkbox is checked. At the moment the input that it validates is always required and not just when the checkbox is checked. here is my validator code:
import { FormControl, AbstractControl } from "../../../node_modules/@angular/forms";
export function validateCheckbox(control:AbstractControl){
const val = control.value;
const check = control.root.get('checkbox'); //i think the problem is here: if i do .value i get an error
if (check) {
if (val === null || val === undefined || val === '') {
return {
validate: {
valid: false
}
};
}else{
return null;
}
}else{
return null;
}
}
My component using the validator:
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { Customer } from '../account/models/customer.model';
import { validateCheckbox } from './customValidators';
@Component({
selector: 'caredeal-registration',
templateUrl: './registration.component.html',
styleUrls: ['./registration.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class RegistrationComponent implements OnInit {
registerForm: FormGroup;
constructor(private formBuilder: FormBuilder) {
this.registerForm = this.formBuilder.group({
name:['',[Validators.required,Validators.minLength(2)]],
firstName:['',[Validators.required,Validators.minLength(2)]],
email:['', [Validators.required,Validators.minLength(2)]],
telephone:['',[Validators.required,Validators.minLength(9)]],
mobilePhone:['',Validators.minLength(10)],
type:[''],
checkbox:[false],
companyName:['',Validators.minLength(2)],
rizivNumber:[''],
taxNumber:['',Validators.minLength(2)],
streetName:['', Validators.required],
houseNumber:['',validateCheckbox],
bus:[''],
zipCode:['',[Validators.required,Validators.minLength(4)]],
place:['',[Validators.required,Validators.minLength(2)]]
})
}
ngOnInit() {
}
}
My html code, the checkbox is at the end of the code, validator is used on housenumber input.
<form [formGroup]="registerForm" (ngSubmit)="onFormSubmit()">
<div class="container-fluid">
<h3>Account informatie</h3>
<div class="row">
<div class="col-md-6">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" class="form-control" formControlName="name" placeholder="Naam">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" class="form-control" formControlName="firstName" placeholder="Voornaam">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
<input type="email" class="form-control" formControlName="email" placeholder="Email">
</div>
</div>
<div class="col-md-6">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-earphone"></i></span>
<input type="tel" class="form-control" formControlName="telephone" placeholder="Telefoon">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-earphone"></i></span>
<input type="tel" class="form-control" formControlName="mobilePhone" placeholder="GSM">
</div>
<div class="input-group">
<label for="sel1">Type klant:</label>
<select class="form-control" formControlName="type">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<h3>Bedrijfsgegevens</h3>
<div class="row">
<div class="col-xs-12">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
<input type="text" class="form-control" formControlName="companyName" placeholder="Bedrijfsnaam">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
<input type="number" class="form-control"formControlName="rizivNumber" placeholder="RIZIV-nummer">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
<input type="text" class="form-control" formControlName="taxNumber" placeholder="BTW-nummer">
</div>
</div>
</div>
</div>
<div class="container-fluid">
<h3>Afleveradres</h3>
<div class="row">
<div class="col-xs-12">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-road"></i></span>
<input type="text" class="form-control" formControlName="streetName" placeholder="Straatnaam">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-sound-5-1"></i></span>
<input type="number" class="form-control" formControlName="houseNumber" placeholder="Huisnummer">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-inbox"></i></span>
<input type="text" class="form-control" formControlName="bus" placeholder="Bus">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-inbox"></i></span>
<input type="number" class="form-control" formControlName="zipCode" placeholder="Postcode">
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-inbox"></i></span>
<input type="text" class="form-control" formControlName="place" placeholder="Plaats">
</div>
<div class="input-group">
<input type="checkbox" formControlName="checkbox" name="">Facturatie adres is verschillend van afleveradres<br>
</div>
<div class="input-group">
<button type="submit" [disabled] = "!registerForm.valid" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
</div>
</form>
Looks like you don't need a custom validator. it is eassier to subscribe to the checkbox and then update the form according to the value of the checkbox. This is my component code now:
export class RegistrationComponent implements OnInit {
registerForm: FormGroup;
bool:boolean = false;
constructor(private formBuilder: FormBuilder) {
this.registerForm = this.formBuilder.group({
name:['',[Validators.required,Validators.minLength(2)]],
firstName:['',[Validators.required,Validators.minLength(2)]],
email:['', [Validators.required,Validators.minLength(2)]],
telephone:['',[Validators.required,Validators.minLength(9)]],
mobilePhone:['',Validators.minLength(10)],
type:[''],
checkbox:[false],
companyName:['',Validators.minLength(2)],
rizivNumber:[''],
taxNumber:['',Validators.minLength(2)],
streetName:['', Validators.required],
houseNumber:[''],
bus:[''],
zipCode:['',[Validators.required,Validators.minLength(4)]],
place:['',[Validators.required,Validators.minLength(2)]]
})
this.formControlValueChanged();
}
setNotification(): void {
this.bool = !this.bool;
if(this.bool){
this.registerForm.root.get('houseNumber').setValidators(Validators.required);
}else{
this.registerForm.root.get('houseNumber').clearValidators();
}
this.registerForm.get('houseNumber').updateValueAndValidity();
}
ngOnInit() {
}
formControlValueChanged() {
this.registerForm.get('checkbox').valueChanges.subscribe(
(mode: string) => {
this.setNotification();
});
}
}
Upvotes: 1
Views: 2295
Reputation: 24464
you can't access to another form control from custome validators you have to create a custome form validator
export function validateCheckbox(fg) {
if (fg.get('checkbox').value) {
let val = fg.get('text').value;
if (val === null || val === undefined || val === '') {
return {
validate: {
valid: false
}
};
} else { // text control has a value
return null;
}
} else { // checkbox value is false
return null;
}
}
component
form: FormGroup;
constructor(fb: FormBuilder) {
this.form = fb.group({
checkbox: [false],
text: ['']
}, { validator: validateCheckbox })
}
Upvotes: 0
Reputation: 60596
I did something similar below:
Above I make the phone required only if the Send Notifications
radio button is set to text.
I do this using the following code:
setNotification(notifyVia: string): void {
const phoneControl = this.customerForm.get('phone');
if (notifyVia === 'text') {
phoneControl.setValidators(Validators.required);
} else {
phoneControl.clearValidators();
}
phoneControl.updateValueAndValidity();
}
So instead of building a validator, this simply adds or clears the required validator on the field. In my example, I only set the validators for one control (phoneControl
), but you could easily set the validators for any number of controls.
This code is called every time the radio button changes using code as shown below. You'd instead need to call the setNotification each time the checkbox is checked:
this.customerForm.get('notification').valueChanges
.subscribe(value => this.setNotification(value));
Upvotes: 1