I have an angular 2 reactive form with four formControl
s and only one input field. What I want is to ask the user to fill up the infos one by one. So I'm assigning the firstControlName
to a property call currentFormControlName
on ngOnInit
and binding it with the input field in template file. When the user fills up his name the field will be valid and on submit I'll change the currentFormControlName
property to next formControlName. But the problem is the binding isn't updating. The input field is still bound to name
. When I type something on the input field the value of name
is updating, not email
.
app.component.ts
ngOnInit() {
this.form = this.builder.group({
'name': ['', Validator.required],
'email': ['', Validator.email],
'phone': ['', Validator.required],
'password': ['', Validator.required],
});
this.currentFormControlName = 'name';
}
submit() {
this.currentFormControlName = 'email'; // Setting it manually just for the demo of this question.
}
app.component.html
<form [formGroup]="form">
<input type="text" [formControlName]="currentFormControlName">
<input type="submit" (click)="submit()">
</form>
Update
You can also use FormControlDirective
to switch between controls
[formControl]="form.get(currentFormControlName)"
Old Answer
Let's say we have the following
template.html
<form [formGroup]="form" #formDir="ngForm">
<input type="text" #controlDir [formControlName]="currentFormControlName">
<input type="submit" (click)="submit()">
</form>
<pre>{{ form.value | json }}</pre>
After clicking on submit button we can change currentFormControlName
and register control with new name like
component.ts
form: FormGroup;
@ViewChild('formDir') formDir: FormGroupDirective;
@ViewChild('controlDir', { read: FormControlName }) controlDir: FormControlName;
currentFormControlName: string;
constructor(private builder: FormBuilder) {}
ngOnInit() {
this.form = this.builder.group({
'name': ['', Validators.required],
'email': ['', Validators.email],
'phone': ['', Validators.required],
'password': ['', Validators.required],
});
this.currentFormControlName = 'name';
}
submit() {
this.formDir.removeControl(this.controlDir);
this.controlDir.name = this.currentFormControlName = 'email'
this.formDir.addControl(this.controlDir);
}
After that our input element will manage email
value. So if we type something in input
it will be reflected in form.email
value
This solution is based on FormControlName source code
ngOnChanges(changes: SimpleChanges) {
if (!this._added) this._setUpControl();
if (isPropertyUpdated(changes, this.viewModel)) {
this.viewModel = this.model;
this.formDirective.updateModel(this, this.model);
}
}
we can see this directive registers control only once. But it also have the following ngOnDestroy hook
ngOnDestroy(): void {
if (this.formDirective) {
this.formDirective.removeControl(this);
}
}
that gave me some idea