Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 8 value won't update on view after change

I have a small component in Angular with a method that (for now) sets a timeout and changes the value of a variable.

import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'my-component',
  templateUrl: './my-view.html',
  styleUrls: ['./my-view.scss'],
  changeDetection: ChangeDetectionStrategy.Default
})
export class MyComponent {

  status: boolean = false;

  changeStatus(): void {

    setTimeout(() => {
      this.status = true;
    }, 1500);
  }
}

And the HTML

<div>
  <form #myForm="ngForm">
    <input name="code" type="text" class="form-control" [(ngModel)]="code" #codeInput="ngModel" required placeholder="Enter your code" />
  </form>
</div>

<div class="row">
  <div class="col-md-5" (click)="changeStatus()">
    <mat-icon aria-label="clear-all" *ngIf="!status">&#xe042;</mat-icon>
    <a>Change status</a>
  </div>
  <div class="col-md-7">
    <button type="button" class="btn-flat app-btn-flat">Cancel</button>
    <button type="button" class="btn app-btn" [disabled]="myForm.invalid || myForm.pristine">Save</button>
  </div>
</div>

If I log the value of 'status' in the component. I get the new value of 'true' but it won't change on the view unless I focus the cursor on the input and then click anywhere outside it.

Why is that happening? how can I solve it?

like image 370
Danny22 Avatar asked Nov 29 '22 21:11

Danny22


2 Answers

Why is that happening?

You set changeDetection to OnPush in one of the ancestor component. That property cannot be overridden. Ref: https://angular.io/api/core/ChangeDetectionStrategy

how can I solve it?

Unset changeDetection in the ancestor component, or manually detect changes like Adam's answer.

constructor(private _cdr: ChangeDetectorRef) {}

changeStatus(): void {
  setTimeout(() => {
    this.status = true;
    this._cdr.detectChanges()
  }, 1500);
}
like image 71
zmag Avatar answered Dec 02 '22 09:12

zmag


You're doing it outside of the normal change detection cycle. This will work:

export class MyComponent {

  status: boolean = false;

  constructor(private _cdr: ChangeDetectorRef) { }

  changeStatus(): void {

  setTimeout(() => {
    this.status = true;
    this._cdr.detectChanges()
  }, 1500);
 }
}

EDIT: It's updating on your next interaction with the UI because angular is running it's change detection at that point in time and it catches the change in your component and updates the UI. If you're doing things asynchronously (unless you're using angular APIs, like HttpService), then you've got to tell the ChangeDetector that there are changes manually.

like image 39
Adam Avatar answered Dec 02 '22 09:12

Adam