Reactive Form with From Builder
6 years ago
Angular
Angular 7
JavaScript
CodePen

Create an input form easily with FormBuilder
Angular comes with a feature to create a dynamic form, FormBuilder. Using FormBuilder to create a form in Angular is intuitively simple.
Example
In this example, Profile Editor below, I am using FormBuilder to dynamically creating a form. The form contains a few group of inputs. There is name consists of first and last name. And another group for address, consists of street, city, state, zip code. And the last one is aliases. Aliases is an example when we want the object to have an array of values instead of just one or any fixed number.
// profile editor
@Component({
selector: 'my-profile-editor',
template: `
<p>
Form Status: {{ profileForm.status }}
</p>
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<label>
First Name:
<input type="text" formControlName="firstName" required>
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
<div formGroupName="address">
<h3>Address</h3>
<label>
Street:
<input type="text" formControlName="street">
</label>
<label>
City:
<input type="text" formControlName="city">
</label>
<label>
State:
<input type="text" formControlName="state">
</label>
<label>
Zip Code:
<input type="text" formControlName="zip">
</label>
</div>
<div formArrayName="aliases">
<h3>Aliases</h3> <button (click)="addAlias()">Add Alias</button>
<div *ngFor="let alias of aliases.controls; let i=index">
<!-- The repeated alias template -->
<label>
Alias:
<input type="text" [formControlName]="i">
</label>
</div>
</div>
<button type="submit" [disabled]="!profileForm.valid">Submit</button>
<button (click)="reset()" class="float-right">Reset</button>
</form>
<hr>
<p>
Form Value: {{ profileForm.value | json }}
</p>
<p>
Form Status: {{ profileForm.status }}
</p>
<p>
<button (click)="updateProfile()">Update Profile</button>
</p>
`,
styles: [`
:host {
display: flex;
flex-direction: column;
padding-top: 24px;
}
label {
display: block;
width: 6em;
margin: .5em 0;
color: #607D8B;
font-weight: bold;
}
input {
height: 2em;
font-size: 1em;
padding-left: .4em;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #ccc;
cursor: auto;
}
`]
})
class ProfileEditor {
// commented for workaround
//constructor(private fb: FormBuilder) {}
// workaround on injection causing "Can't resolve all parameters" error
constructor() {}
// end of workaround
private fb: FormBuilder = new FormBuilder()
profileForm = this.fb.group({
firstName: ['', Validators.required],
lastName: [''],
address: this.fb.group({
street: [''],
city: [''],
state: [''],
zip: ['']
}),
aliases: this.fb.array([
this.fb.control('')
])
})
ngOnInit() {}
get aliases() {
return this.profileForm.get('aliases') as FormArray
}
addAlias() {
this.aliases.push(this.fb.control(''))
}
onSubmit() {
// TODO: Use EventEmitter with form value
console.warn(this.profileForm.value);
}
updateProfile() {
this.profileForm.patchValue({
firstName: 'Nancy',
address: {
street: '123 Drew Street'
}
})
}
reset() {
this.profileForm.reset()
}
}
Updated
See this in my codepen for preview and quick tinkering.