2

i am trying to build a simple component within my app for a countdown. i keep getting this uncaught error whenever i ng serve. please a little help, i am stomped

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { ContentComponent } from './content/content.component';
import { CountdownComponent } from './countdown/countdown.component';

@NgModule({
 declarations: [
    AppComponent,
    ContentComponent,
    CountdownComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

<app-count></app-count>

countdown.component.ts

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

@Component({
selector: 'app-count',
templateUrl: './countdown.component.html',
styleUrls: ['./countdown.component.css']
})

export class CountdownComponent {
dayleft: 100;

constructor(days: any) {
    setTimeout(() => {
        days = this.dayleft;
        days--;
    }, 1000);
}
}

countdown.component.html

<p>{{ daysleft }}</p>
Muhammed Albarmavi
  • 23,240
  • 8
  • 66
  • 91
mitch
  • 67
  • 2
  • 11

3 Answers3

1

Remove days from the constructor parameter and pass it via @Input. Angular can't inject days: any in the constructor. I think also you don't need daysleft property.

export class CountdownComponent {

   @Input() days;

   constructor() {
      setTimeout(() => {
        this.days--;
      }, 1000);
   }

}

and use like

<app-count [days]="100"></app-count>

Here 100 will be passed into the CountdownComponent and initialize days property with 100.

Suren Srapyan
  • 66,568
  • 14
  • 114
  • 112
1

The reason behind the error:

When the angular finds the tag <app-count></app-count>, he will tries to initialize the component CountdownComponent by matching the html tag with the selector property in the CountdownComponent decorator. This means that the angular code will try to do something like this:

let countdownComponent: CountdownComponent = new CountdownComponent()

Because you define the days as a mandatory parameter, the angular does not know how to resolve the parameters that you define and that causes the error.

First solution:

You can tell to the angular witch is the value of the days by using the @Input decorator and by passing in the HTML which value will be passed.

<app-count [days]=100></app-count>

export class CountdownComponent {
    @Input()
    dayleft: number = 100;

    constructor(days: any) {
        setTimeout(() => {
            days = this.dayleft;
            days--;
        }, 1000);
    }
}

Second solution: You can set the parameters as optional or default parameters.

constructor(days: any = 100) {
    setTimeout(() => {
        days = this.dayleft;
        days--;
    }, 1000);
}

//or

constructor(days?: any) {
    if(!days) days = 100;
    setTimeout(() => {
        days = this.dayleft;
        days--;
    }, 1000);
}
Ricardo Rocha
  • 14,612
  • 20
  • 74
  • 130
  • the second solution fits perfectly. Much appreciation for your time – mitch Aug 14 '18 at 18:00
  • Thank you @mitch. Each time you like an answer upvotes. Also, if you think that the answer solves your issue, please accepted as the best answer – Ricardo Rocha Aug 14 '18 at 19:29
1

Yes that right to add days as a pramater to class constructor but here you are not the one how create and initialise the CountdownComponent instant angular do that for you,that why you got an error Can't resolve all parameters for CountdownComponent: (?) , when you add a pramater to componenet constracter angular try to inject by Angular DI system,in this case you may create inject value and provid this to class constructor by @Inject decorator.

create inject value

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, HelloComponent, CountComponent ],
  bootstrap:    [ AppComponent ],
  providers:[{provide:'days',useValue:100}]
})
export class AppModule { }

component

export class CountComponent implements OnInit {

  id: any; // to clear setInterval 
  constructor( @Inject('days') private days: number) { }

  ngOnInit() {
    this.id = setInterval(() => {
      --this.days
      if (this.days === 0) {
        clearInterval(this.id)
      }
    }, 1000)
  }

}

count template

{{days}}

app component

<app-count></app-count>

stackblitz demo

Another solution is create Input property and use it like @Suren Srapyan said

Muhammed Albarmavi
  • 23,240
  • 8
  • 66
  • 91