Zerok
Zerok

Reputation: 227

Proper way of initializing components in Angular 2 via HTML

I've got a component that gets some parameters from outside, and then, builds the rest of its properties depending on those parameters:

import { Component, Input } from '@angular/core';
import { NavController } from 'ionic-angular';

/*  
    Info card for displaying information in the homepage or another places
*/

@Component({
  selector: 'info-card',
  templateUrl: 'infocard.html'
})

export class InfoCard {
  icon;
  @Input() card = {
    title: '',
    description: '',  
    image: null,
    type: 0
  }


  constructor(public navCtrl: NavController) {

      // TODO: Complete type list
    switch(this.card.type){
        case 0:  // Pubs/Entertainment
            this.icon = "beer"; break;
        case 1:  // Restaurants
            this.icon = "restaurant"; break;
        case 2:  // Friends
            this.icon = "person"; break;
        case 3:  // Groups of people (private chats)
            this.icon = "people"; break;
        case 4:  // Objective
            this.icon = "checkbox-outline"; break;
        default:
            this.icon = "alert"; break;
    }

    // Image path
    if(this.card.image){
        this.card.image = '../../assets/infocards/'+this.card.image;
    }

  }

}

There you can see in the constructor, how depending on the type of the card, its icon gets set. Also, the image will only get rendered if it's different from "null", but I only want to pass from outside its name, so I put inside the constructor the real path to the folder, and concatenate the image name at the end.

Nothing strange I guess. Then, I try to use this component in my code:

 <info-card *ngFor="let card of testCards" [card]="card">

 </info-card>

The cards display "correctly". I mean, the template is rendering ok and so, but both the icon and the image, which depend of the constructor, aren't working properly. The type 0 is always present, so I always see the "beer" icon, and the image is broken (because it's not pointing to the right directory, but to a name).

This leads to the following question: when does the constructor run? I thought that an @Input value would be added before the constructor initialization, but I guess I was wrong.

What should I do to properly build my component passing its data from the HTML?

I just want to execute some code after the property "card" has been passed to the component!

Upvotes: 2

Views: 1682

Answers (1)

Fabio Antunes
Fabio Antunes

Reputation: 22862

You need to use the OnChanges :

import { Component, Input, OnChanges } from '@angular/core';
import { NavController } from 'ionic-angular';

/*  
    Info card for displaying information in the homepage or another places
*/

@Component({
  selector: 'info-card',
  templateUrl: 'infocard.html'
})

export class InfoCard implements OnChanges {
  icon;
  @Input() card = {
    title: '',
    description: '',  
    image: null,
    type: 0
  }


  constructor(public navCtrl: NavController) {

  }

  ngOnChanges(changes) {
    //changes will have your old card value and the new one
    switch(this.card.type){
        case 0:  // Pubs/Entertainment
            this.icon = "beer"; break;
        case 1:  // Restaurants
            this.icon = "restaurant"; break;
        case 2:  // Friends
            this.icon = "person"; break;
        case 3:  // Groups of people (private chats)
            this.icon = "people"; break;
        case 4:  // Objective
            this.icon = "checkbox-outline"; break;
        default:
            this.icon = "alert"; break;
    }

    // Image path
    if(this.card.image){
        this.card.image = '../../assets/infocards/'+this.card.image;
    }
  }

}

Upvotes: 2

Related Questions