2

I use Angular 9 and modify a variable that I use in a template. But unfortunately my template does not get updated. Can anyone explain me what the typical approach is to let Angular know that something in my component changed?

projects: any[] = [];
ngAfterViewInit(): void {
    this.actRoute.params.subscribe((params) => {
        this.electronService.foo.bar(
        .then((x) => {
            var history = x.y();

            history.on("begin", () => {
                this.projects.push('foo');
            });
            history.execute();
        });
    });
}

foo.component.html

<ul>
  <li *ngFor="let project of projects;">{{project}}</li>
</ul>
0

3 Answers 3

2

Angular will not detect the changes if you don't change the "in memory" variable. In your case, just pushing the same variable will not trigget the change detection. You should this.projects = this.projects.slice() or something like that to change the memory variable and trigger the change. If that doesn't fit you, there are other things you can use like Injecting ChangeDetector then calling ChangeDetector.detectChanges();

constructor(private cd: ChangeDetectorRef) {}

...
this.projects.push('foo');
this.cd.detectChanges();
...
Sign up to request clarification or add additional context in comments.

3 Comments

I don't know who downvoted your post, but it works! Thank you so much. Is there anything seen to be as a side effect?
The side effect is that the changedetector trigger the change from the view in a whole. So if you have too many inputs or interpolations on your page on the moment, it will cost some performance. Changing in memory variable has no cost at all. Not that I know.
I have an end event as well, so I don't trigger detectChanges for every event. Thanks again!
1

You need to use the arrow function. this doesn't have the same meaning as you think it does

ngAfterViewInit(): void {
    let projects = this.projects;
    projects = [];

    this.actRoute.params.subscribe((params) => {
        this.electronService.foo.bar(
          .then((x) => { // arrow function
            const history = x.y(); // use const

            history.on("begin", () => { // arrow function
              projects.push('foo');
            });
            history.execute();
          });
        });
    }

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

4 Comments

Thank you for the clarification! That explains actually a lot now in my code. However, changing the code still doesn't update the Angular view :-/. Is this maybe caused due to the event handlers where Angular doesn't notice any changes?
Could be something in your electronService. Make sure you're using arrow functions there as well
Thanks! I verified that it gets properly executed. If I "manually" refresh the "page" the entries are visible. It seems to me the change is done outside Angulars zone, but don't know how I can make Angular aware of that change
import ChangeDetectorRef and then run ChangeDetectorRef.detectChanges() after your update. But, I would recommend debugging that further to figure out the actual problem rather than implement the "workaround". Sounds like your problem revolved around the lifecycle hook or scope.
1

You must assign the new value to the variable you want to see changed (project) otherwise Angular will not notice the change because the value of your variable is of type object.

The answer is this: this.projects = this.projects.concat(['foo'])

Instead of: this.projects.push('foo') (which is "wrong" in Angular)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.