1

I have a simple timer in my searchstatusComponent:

import { Component, OnInit, DoCheck, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-searchstatus',
  templateUrl: './searchstatus.component.html',
  styleUrls: ['./searchstatus.component.scss']
})
export class SearchstatusComponent implements OnInit, DoCheck, OnDestroy {

  intervalId = 0;
  seconds = 0;
  minutes = 0;
  message = '';

  constructor() { }

  ngOnInit() {
    // this.start();
  }

  ngDoCheck() {
  }

  ngOnDestroy() {
    this.clearTimer();
  }

  start() {
    this.minutes = 0;
    this.seconds = 0;
    this.countTime();
    console.log('starting');
  }

  stop()  {
    this.clearTimer();
  }

  private countTime() {
    this.clearTimer();
    this.intervalId = window.setInterval(() => {
      this.seconds += 1;
      this.message = `${this.minutes} min., ${this.seconds} sec`;
      if (this.seconds === 60) {
        this.minutes++;
        this.seconds = 0;
      }
    }, 1000);
  }

  clearTimer() {
    clearInterval(this.intervalId);
  }

}

and in my SearchstatusComponent.html

<div>Elapsed Time: {{message}}</div>

Now when I trigger start() from onInit() everything works fine.. BUT if I trigger start() from the parent component, the variable in the template simply does not get updated (?)

the method runs, i can see this in the console, the only thing is the display in the template. what am I doing wrong?

https://stackblitz.com/edit/angular-vpjeu2

Mka24
  • 369
  • 1
  • 3
  • 8
  • You could try to force it to run in ngZone. e.g. by wrapping your countTime body code within a `ngZone.run(() => {...})`. (see https://angular.io/api/core/NgZone for more info) – Ploppy Feb 13 '18 at 13:50
  • Could you make a stackblitz of this issue ? It's hard to play with Angular without sandboxes. –  Feb 13 '18 at 13:50
  • @Ploppy .. just tried it, but with no effort.. still the same beaviour – Mka24 Feb 13 '18 at 14:08
  • @trichetriche .. sure .. https://stackblitz.com/edit/angular-vpjeu2 .. just uncomment the `this.start()` in the `onInit()` and it runs correctly.. but if I trigger the func from the parent-component.. th output in the HTML does not work – Mka24 Feb 13 '18 at 14:19
  • Can you please use the share buttton in stackblitz and post the link from there? – Günter Zöchbauer Feb 13 '18 at 14:21
  • sorry ..updated the link :) – Mka24 Feb 13 '18 at 14:22
  • Injecting a component is almost always wrong. `providers: [SearchstatusComponent]` creates an instance of the `SearchstatusComponent`'s class that is not a component and a new instance entirely unrelated to any component used in your app. You might want to have a look at https://stackoverflow.com/questions/32693061/how-can-i-select-an-element-in-a-component-template/35209681#35209681 – Günter Zöchbauer Feb 13 '18 at 14:23

2 Answers2

1

It won't work because you're injecting a component as a dependency. But you don't specify which instance of the component you are actually injecting. And it's definitely neither a singleton, nor the one you have in your app component.

Here is a stackblitz that shows your error.

  @ViewChild(SearchstatusComponent) searchStatus: SearchstatusComponent;
  constructor() {}
  ngOnInit() { this.searchStatus.start(); }

In your HTML

<app-searchstatus #searchStatus></app-searchstatus>
0

Instead of injecting the component, you can use

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
})
export class AppComponent  {

  @ViewChild(SearchstatusComponent) _status:SearchstatusComponent;

  ngAfterViewInit() {
    this._status.start();
  }
}

StackBlitz example

Injecting a component is almost always wrong.

providers: [SearchstatusComponent] creates an instance of the SearchstatusComponent's class that is not a component and a new instance entirely unrelated to any component used in your app.

You might want to have a look at How can I select an element in a component template?

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567