Increase performance on Angular2 inputfield
Asked Answered
K

2

2

I have a list of components that contain dates(formatted with toLocaleString()) and other things. On top of them there is a component for creating new components, wich contains a form with some inputfields built with angulars FormBuilder. When I type fast the validation lags and the text I'm typing isn't displayed immediately.

I assume that Angular is rerendering all components, because if I don't display the date in the other components I can type pretty fast without lags.

Is there a way to only rerender the input field I'm typing in, since all other components cannot change or is toLocaleString() the problem?

Krall answered 18/4, 2016 at 14:5 Comment(1)
could you provide sample plunker?Panslavism
S
6

Is there a way to only rerender the input field I'm typing in, since all other components cannot change

Yes, for the components that will not change, set the change detection strategy for those components to OnPush. An OnPush component will then only be checked for changes if

  • any of its input properties changes
  • it fires an event (e.g., a button click)
  • an observable (which is an input property or a local-to-the-component property) fires an event, and | async is used in the template with the observable (see plunker in the comments below this answer)
import {Component, Input, ChangeDetectionStrategy} from 'angular2/core';

@Component({
  ...
  changeDetection: ChangeDetectionStrategy.OnPush
})

Also consider listening for changes to your input by subscribing to the valueChanges Observable Angular makes available on your form element if you use ngFormControl. You can then use debounce() to only process changes every second or whatever time frame is appropriate:

<input type=text [ngFormControl]="input1Control">
constructor() { 
  this.input1Control = new Control();
}
ngOnInit() {
  this.input1Control.valueChanges
    .debounceTime(1000)
    .subscribe(newValue => console.log(newValue))
}

See https://mcmap.net/q/49644/-angular-2-and-debounce for a working plunker.

Selfappointed answered 25/4, 2016 at 16:49 Comment(6)
I haven't found any mention of the "observable fires an event". In this blog they explicitely call markForCheck in the subscribe(...) callback. Maybe this is only with | async?Valiant
@GünterZöchbauer see victorsavkin.com/post/110170125256/… and #35387322. In the thoughtram blog you mention, I don't really like the example they give, since they are only changing view state, so markForCheck() is overkill... they only need to call detectChanges(). I need to play around with this some more (someday)... as I'm not sure what Victor really means when he says "an observable fires an event". If you figure it out, please comment.Selfappointed
@GünterZöchbauer, I created a Plunker to test this, and what you said is true: if an input property that is an observable fires an event AND | async is used in the template, then the view updates. If async isn't used, the view does not update. (Savkin's blog is likely outdated.) But this seems odd to me -- bug? If I imperatively subscribe(), I would expect it to work the same way that async works (i.e., the declarative/implicit subscribe() way).Selfappointed
I read Victors blog yesterday and was constanrly wondering where and how the "magic" could happen but couldn't find a hint (I assumed because being too tired). Angular can only know about events of observables when it subscribes them (that's what async does). I would find it weird if Angular would subscribe and consume an observable (if it's not shared) without me explicitely telling to do so. And as Victor said, they don't require a specific observable implementation there is IMHO no way to patch it like they do with the async API.Valiant
There were a few questions in the comments about this as well and the answers are vague. My impression is they planned to make it work like magic back then and ended with | async because there is no proper "magic" available for this use case. Thanks a lot for your feedback about your attempt to reproduce!Valiant
@GünterZöchbauer, thanks for this: "there is no way to patch it like they do with the async API". I assumed it was/could be patched -- i.e, I assumed subscribe() was patched. I guess not. And thanks for asking the question (i.e., your original comment)... this was interesting (even if I lost some sleep over it).Selfappointed
P
2

That's a known issue https://github.com/angular/angular/issues/6311

See also

There is also a pull request with a proposed fix, but seems not to be included in the latest beta release.

Persiflage answered 18/4, 2016 at 14:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.