I have a form to update just part of the field of an existing model class in angular 4.
I need to setValue on the current model instance and at the end get the value back updated.
The issue is I need to update only parts of the model but the angular forms returns an error
"Cannot find form control with name 'fieldname'"
for the extra fields that I do not want to edit.
What is my best option to get the needed behavior?
I thought about adding hidden formControls for the fields I do not want to update in the forms but some of our models are pretty big while we need the user to only edit parts of them.
I have to get an updated model at the end for dirty checking and generic updating of our models (compared to having multiple duplicate class relevant code just for setting the values of all the formControls and updating the models back from the formControls on submit)
Thanks.
UPDATE just for clarification - I want a behavior that is similar to this:
--component.ts
model: Model = someModelWithData;
--component.html
<input type="checkbox" [(NgModel)]="model.FieldOne" />
After the user changes the value in FieldOne, the model is still full with all other data but with FieldOne changed.
We use the SetValue to update the FormControl , FormGroup or FormArray . When we use it to update the FormGroup or FormArray the SetValue requires that the object must match the structure of the FormGroup or FormArray exactly. Otherwise, it will result in an error.
In Angular, a reactive form is a FormGroup that is made up of FormControls. The FormBuilder is the class that is used to create both FormGroups and FormControls. I encourage you to check out those links to see the full class definitions of all three.
How to add a FormControl to a FormGroup. To add, update, or remove controls in FormGroup , use the following commands: addControl() adds a control and updates its value and validity. removeControl() removes a control.
[formControl] assigns a reference to the FormControl instance you created to the FormControlDirective . formControlName assigns a string for the forms module to look up the control by name.
You can update parts of your form with the method patchValue
instead of setValue
.
this.yourForm.patchValue({
yourFieldToUpdate: yourValue
});
Angular is built in such a way to keep the form model and data model separate.
From the documentation:
In keeping with the reactive paradigm, the component preserves the immutability of the data model, treating it as a pure source of original values. Rather than update the data model directly, the component extracts user changes and forwards them to an external component or service, which does something with them (such as saving them) and returns a new data model to the component that reflects the updated model state.
But if you want to bind to a data model inside of a form, you can set ngModelOptions standalone to true
standalone: Defaults to false. If this is set to true, the ngModel will not register itself with its parent form, and will act as if it's not in the form. This can be handy if you have form meta-controls, a.k.a. form elements nested in the tag that control the display of the form, but don't contain form data.
Stack Blitz Example
In this example, the model has 3 fields, 2 of which can be edited on the form.
model.ts
export class Model {
fieldOne: string;
fieldTwo: string;
fieldThree: string;
constructor(fieldOne: string, fieldTwo: string, fieldThree: string)
{
this.fieldOne = fieldOne;
this.fieldTwo = fieldTwo;
this.fieldThree = fieldThree;
}
}
app.component.ts
import {Component, OnInit} from '@angular/core';
import {AbstractControl, FormBuilder, FormGroup} from '@angular/forms';
import {Model} from './model';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
private _form
private _model: Model;
get form(): FormGroup {
return this._form;
}
get model(): Model {
return this._model;
}
set model(model: Model) {
this._model = model;
}
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.model = this.newModel();
this.createForm();
}
private newModel(): Model {
return new Model('fieldOne', 'fieldTwo', 'fieldThree');
}
private createForm() {
this._form = this.formBuilder.group({
});
}
}
app.component.html
As the form values change, the actual data model is updated and only editable fields have been exposed to change via the form.
<form [formGroup]="form">
<div>
<label for="fieldOne">Field One</label>
<input
id="fieldOne"
type="text"
[(ngModel)]="model.fieldOne"
[ngModelOptions]="{ standalone: true }">
</div>
<div>
<label for="fieldTwo">Field Two</label>
<input
id="fieldTwo"
type="text"
[(ngModel)]="model.fieldTwo"
[ngModelOptions]="{ standalone: true }">
</div>
</form>
<h3>Model</h3>
<pre>{{ model | json }}</pre>
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