dombr
dombr

Reputation: 31

Angular2 change detection in lifecycle hook methods

I want to show a spinner in ngOnInit() and hide it in ngAfterViewInit(). But this is not working:

http://plnkr.co/edit/M1g7DT1Eks2gtuSXi1B1?p=preview

In this example the spinner component (spinner.ts) is a div tag that changes background color.

import {Component, Input} from '@angular/core'

@Component({
  selector: 'my-spinner',
  template: `
    <div [style.background-color]="status ? 'red' : 'yellow'" >
      spinner is {{status}}
    </div>
  `,
})
export class MySpinner {
  @Input() status: boolean;

  status:boolean;
  constructor() {
    this.status = false;
  }

  getColor() {
    if (status) {
      return "red";
    } else {
      return "yellow";
    }
  }

  ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
        for (let propName in changes) {
            let chng = changes[propName];
            let cur  = JSON.stringify(chng.currentValue);
            let prev = JSON.stringify(chng.previousValue);
            console.trace(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
        }
    }
}

On clic on 'link to my component' (mycomponent.ts), I want the background color spinner is red between ngOnInit() and ngAfterViewInit().

import {Component, Input, ApplicationRef} from '@angular/core';
import {AppService} from './appservice';

@Component({
  selector: 'my-component',
  template: `
    <div>
      This is my component!
    </div>
  `,
})
export class MyComponent {

  constructor(private appSvc: AppService) {

  }

  ngOnInit(): void {

    this.appSvc.setVisible(true);
    console.log('MyComponent - ngOnInit');
  }

  ngAfterViewInit() {
    var start = new Date().getTime();
        for (var i = 0; i < 1e7; i++) {
            if ((new Date().getTime() - start) > 10000){
                break;
            }
        }

    //setTimeout(() => { this.appSvc.setVisible(false)});
    this.appSvc.setVisible(false);

    console.log('MyComponent - ngAfterViewInit');
  }

}

What is the solution?


UPDATE

I update the sample http://plnkr.co/edit/M1g7DT1Eks2gtuSXi1B1?p=preview to use observable.

I set the spinner to show in ngOnInit() but ngOnChanges() of the spinner component is called after ngAfterViewInit()

The log console is :

VM437 AppService - setVisible - true  
VM439 mycomponent.ts!transpiled:33 MyComponent - ngOnInit  
VM439 mycomponent.ts!transpiled:37 MyComponent - ngAfterViewInit -begin  
VM439 mycomponent.ts!transpiled:47 MyComponent - ngAfterViewInit -end  
**VM440 spinner.ts!transpiled:38 status: currentValue = true, previousValue = fals**  
VM437 appservice.ts!transpiled:27 AppService - setVisible - false  
VM439 mycomponent.ts!transpiled:45 Observable Complete  
**VM440 spinner.ts!transpiled:38 status: currentValue = false, previousValue = true**

So it seems that there is no immediately change detection in lifecycle hook methods? Right or wrong?

Upvotes: 2

Views: 774

Answers (1)

dokkis
dokkis

Reputation: 366

To achieve this, I think it's better put directly the spinner as non-angular component inside the <my-app> tags. In this way, you can obtain a spinner that display until the application is fully loaded.

If you try to achieve this using angular components, the spinner does not show until the angular app is loaded, and when it is loaded the spinner at that moment is useless.

Upvotes: 0

Related Questions