I know that if I use a method call in a template it will get executed over and over (not ideal). I have solved that by using a combination of pure pipes and memoized methods. But I am also using reactive forms and in my template using the myFormGroup.get('myFormControl').value to get the values. Will this too get executed repeatedly like the method in my component or does Angular have a strategy in place to prevent this? A usage example is using *ngIf and having the conditional be based on a value of the form.
Also, I am not experiencing any performance degradation currently, but I would like to implement this in the best way possible before getting too far down the road with this application (and am just curious).
I can easily update it to reference the properties on the form object directly, I just prefer the syntax of the method call. Any insight would be helpful, thanks!
With reactiveforms, you create a tree of Angular form control objects in the component class and bind them to native form control elements in the component template, using techniques described in this guide. You create and manipulate form control objects directly in the
Template-driven forms are the default way to work with forms in Angular. With template-driven forms, template directives are used to build an internal representation of the form. With reactive forms, you build your own representation of a form in the component class.
There are 2 ways to build a form in Angular — Template-Driven and Reactive approaches. Here we will focus on the Reactive approach. The Reactive approach is supposed a two-step process. First, we need to create a model programmatically and then link HTML elements to that model using directives in the template.
Angular application-design fundamentals, as described in Angular Concepts The form-design concepts that are presented in Introduction to Forms Reactive forms use an explicit and immutable approach to managing the state of a form at a given point in time.
This is what happens when you call AbstractControl.get(...)
:
get(path: Array<string|number>|string): AbstractControl|null {
return _find(this, path, '.');
}
Source.
And the _find
function looks like this:
function _find(control: AbstractControl, path: Array<string|number>|string, delimiter: string) {
if (path == null) return null;
if (!Array.isArray(path)) {
path = path.split(delimiter);
}
if (Array.isArray(path) && path.length === 0) return null;
// Not using Array.reduce here due to a Chrome 80 bug
// https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
let controlToFind: AbstractControl|null = control;
path.forEach((name: string|number) => {
if (controlToFind instanceof FormGroup) {
controlToFind = controlToFind.controls.hasOwnProperty(name as string) ?
controlToFind.controls[name] :
null;
} else if (controlToFind instanceof FormArray) {
controlToFind = controlToFind.at(<number>name) || null;
} else {
controlToFind = null;
}
});
return controlToFind;
}
Source.
As you noticed, you can get descendants that reside deeper in the form control tree.
For instance:
form.get('a.b.c')
// Or
form.get(['a', 'b', 'c'])
This whole logic involes an iteration, because it's iterating over each element from path
.
Will this too get executed repeatedly like the method in my component
I'd say it will.
I've created a StackBlitz demo to illustrate this:
@Component({
selector: 'my-app',
template: `
<form [formGroup]="form">
<input formControlName="name" type="text">
</form>
<hr>
<p>
Getter value: {{ name.value }}
</p>
`,
styleUrls: ['./app.component.css']
})
export class AppComponent {
form: FormGroup;
name2: FormControl
get name (): FormControl {
console.log('getter invoked!')
return this.form.get('name') as FormControl;
}
constructor (private fb: FormBuilder) { }
ngOnInit () {
this.form = this.fb.group({ name: '' });
this.name2 = this.form.get('name') as FormControl;
}
}
If you're using a getter
, you should see getter invoked!
logged twice for each character you type in the input(and the get
method called multiple times as well).
If you're using {{ form.get('name').value }}
, the AbstractControl.get
method will be called multiple times, more than expected.
You can test this by opening the dev tools, typing forms.umd.js
and placing a log breakpoint
at this line path.forEach(function (name) {...}
, inside _find
function's body.
And if you're using this.name2 = this.form.get('name') as FormControl;
, you should see nothing logged as you're typing.
In my opinion, it's less likely that the visible performance will decrease if you're using a getter
or .get()
, but I'd go with the third approach, creating a separate property
for the control I'll be using in the view.
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