I am trying to implement a model-driven form in Angular 2. The structure of my data model is as follows:
archive (FormGroup)
name (FormControl)
description (FormControl)
connection (FormGroup)
url (FormControl)
authentication (FormGroup)
username (FormControl)
password (FormControl)
Within this data model, the top-level name is required but the description field is optional. I can apply a required validator to name, and omit a validator from description.
For the connection, I want it to be optional but if a connection is present its URL becomes required. Similarly for the authentication model of the connection: It is optional but if present the username and password would be required.
I am trying to understand how to set up validators to enforce these rules. I have tried just omitting any validators from the connection form group, but that seemed to be requiring me to have a connection. I've seen online tutorials explaining how to implement custom validation on a nested form groups but nothing that describes how to make the entire nested formgroup optional.
Is there a straightforward way to implement this model with Angular 2 FormGroup?
I had a similar need and here is a way to solve it:
this.form = new FormGroup({
'name': new FormControl(null, Validators.required),
'description': new FormControl(null),
'connection': new FormGroup({
'url': new FormControl(null),
'authentification': new FormGroup({
'username': new FormControl(null, Validators.minLength(5)),
'password': new FormControl(null),
}, this.authentificationValidator.bind(this)),
}, this.connectionValidator.bind(this))
});
The 2 validator functions:
authentificationValidator(g: FormGroup): any {
const username = g.get('username').value;
const password = g.get('password').value;
if( (username && !password) || (!username && password) ) {
return {
authentification: true
};
}
}
connectionValidator(g: FormGroup): any {
const url = g.get('url').value;
const authentification = g.get('authentification');
const username = authentification.get('username').value;
const password = authentification.get('password').value;
if( (username || password) && !url ) {
return {
connection: true
};
}
}
And for the output, if you fill only the name, you will still have:
{
"name": null,
"description": null,
"connection": {
"url": null,
"authentification": {
"username": null,
"password": null
}
}
}
So you have to conditionnaly create a new object to have:
{
"name": null,
"description": null,
"connection": null
}
Check this plunker to experiment this solution
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With