mb925
mb925

Reputation: 137

view not updating after variable change

I have an event that triggers a function in the component:

componentA.ts

    html = 'hey';

      this.onElementSelected(r => this.change());

      public change() {

      console.log(this.html);
      if (this.html === 'hey') {

        this.html = 'oh, hello!';
        console.log(this.html);
      } else {
        this.html = 'hey';
      }
  }

componentA.html

This is the code of the associated template:

<div *ngIf="html">{{html}}</div>

I can see the html variable change with console.log(), but it doesn't change in the template. How to update the template? Please do not suggest to use a button in the template as so:

  <button (click)="change()">Change</button>

I already tested this and it works, but I need the event of change to be triggered by the component itself.

Thank you for your help.

Upvotes: 0

Views: 2944

Answers (3)

Bastian Krones
Bastian Krones

Reputation: 51

Did you use ChangedetectionStrategy.OnPush? This option decouples Angular from auto updating your view. Hence you have to tell when Angular should update the view.

If so tell your component's view to update:

  1. inject the ChangeDetectorRef via your constructor:
import { ChangeDetectorRef } from '@angular/core';

...

constructor(private cd: ChangeDetectorRef) {}
  1. tell Angular to rerender the component by calling in your change()-function after the 'this.html'-assignment:
if (this.html === 'hey') {
        this.html = 'oh, hello!';
        this.cd.detectChanges();
...

Upvotes: 2

Mike Araya
Mike Araya

Reputation: 164

try injecting ngZone in your component and execute your change in its run function like so

import {NgZone} from '@angular/core';  

class YourClass {

        constructor(private ngZone: NgZone) {
                this.htmlSource = new BehaviorSubject('hey');
               this.html$ = this.htmlSource.asObservable();
          }

     this.onElementSelected(r => this.change());

    public change() {
         console.log(this.htmlSource.value);
    this.ngZone.run(() => {
     if (this.htmlSource.value === 'hey') {
          this.htmlSource.next('oh, hello!');
         console.log(this.htmlSource.value);
     } else {
        this.htmlSource.next('hey');
     }

     });
   }
}

Upvotes: 1

German Quinteros
German Quinteros

Reputation: 1930

Try using an Observable with BehaviorSubject like this:

public html$: Observable<string>;
private htmlSource: BehaviorSubject<string>();
constructor() {
   this.htmlSource = new BehaviorSubject('hey');
   this.html$ = this.htmlSource.asObservable();
}
  this.onElementSelected(r => this.change());

  public change() {

  console.log(this.htmlSource.value);
  if (this.htmlSource.value === 'hey') {

    this.htmlSource.next('oh, hello!');
    console.log(this.htmlSource.value);
  } else {
    this.htmlSource.next('hey');
   }
}

Then in the component.html:

<div *ngIf="html$ | async as html">{{html}}</div>

Upvotes: 0

Related Questions