Créer un composant sous Ionic 3

Composant, composant, composant ! Vous devez vous le dire dans votre tête le futur du web, c’est les composants ! voyons voir comment on peut générer un composant et l’utiliser dans Ionic 3, il est important d’en utiliser quand vous créez une application qui commence à grossir.

Génération d’un composant dans Ionic 3

Pour générer des composants comme pour les services, il est très recommandé de la faire en ligne de commande, car il y a des opérations sous le capot qui se font et si vous n’êtes pas familier du framework, ne vous aventurez pas à le faire à la main.

ionic generate component components/loginForm

Définition du code en Typescript du composant

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

/**
 * Generated class for the LoginformComponent component.
 *
 * See https://angular.io/api/core/Component for more info on Angular
 * Components.
 */
@Component({
  selector: 'loginform',
  templateUrl: 'loginform.html'
})
export class LoginformComponent {

  text: string;

  constructor() {
    console.log('Hello LoginformComponent Component');
    this.text = 'Hello World';
  }

}

Important !

Vous concevez un custom component et vous utilisez des éléments Ionic dans votre formulaire, vous aurez le message d’erreur suivant, et c’est plutôt mal documenté :

‘ion-input’ is not a known element

‘ion-card-header’ is not a known element

Il semble que ce genre de situation est dû au lazy loading (je ne suis pas encore assez expert). Néanmoins voici la recette que j’ai trouvé pour résoudre ce problème. Dans le code de votre composant (à supposer que vous avez fait un Shared Module, importez IonicModule, et dans le décorateur @NgModule, et remplissez l’attribut imports : ci-dessous, le fichier components.module.ts qui rassemble tous les components que vous créez, et s’appelle un shared module, qui va rassembler tous les composants, ceci vous évite d’importer à chaque fois tous les components un par un, il suffit d’importer ComponentsModule seulement.

Code Typescript du shared Module

import { NgModule } from '@angular/core';
import { IonicPageModule, IonicModule } from 'ionic-angular';
import { TimerComponent } from './timer/timer';
import { LoginformComponent } from './loginform/loginform';

@NgModule({
	declarations: [TimerComponent,
    LoginformComponent],
	imports: [IonicModule
	],
	exports: [TimerComponent,
    LoginformComponent]
})
export class ComponentsModule {}

J’ai trouvé cette solution sur cette page, mais j’avoue que la documentation n’est pas très loquace, d’autant plus qu’on fait souvent des composants.

Maintenant il faut associer le fichier html qui va avec.

<!-- Generated template for the LoginformComponent component -->
<div class="connexion">
  <ion-input type="mail" placeholder="Adresse email"></ion-input>
  <ion-input type="password" placeholder="Mot de passe"></ion-input>
</div>

<button class="btn-style" (click)="goToPage()">Se connecter</button>

Et l’utilisation dans un template d’une page quelconque se fait de la façon suivante ( le selector dans la définition )

<ion-content>
    <div class="main-appli home" >
       <div class="content-accueil">
           <loginform></loginform>
        </div>
    </div>
</ion-content>

Echange de données entre composant parent et fils

Soit le composant fils:

#template HTML
<div class="connexion">
  <ion-input type="mail" [(ngModel)]="email" placeholder="Adresse email"></ion-input>
  <ion-input type="password" [(ngModel)]="password" placeholder="Mot de passe"></ion-input>
</div>

<button class="btn-style" (click)="checkLogin()">Se connecter</button>

#code TS
import {Component, EventEmitter, Output} from '@angular/core';
...
@Component({
  selector: 'loginform',
  templateUrl: 'loginform.html'
})
export class LoginformComponent {

  email: string;
  password: string;
  @Output() valueChange = new EventEmitter();

  constructor(public http: HttpClient) {
    this.email = '';
    this.password = '';
  }

  private connect() {
    let url = `url/vers/page/authentification/?email=${this.email}&mdp=${this.password}`;
    return this.http.get(url);
  }

  checkLogin(){
    let observable = this.connect();
    observable.subscribe(
        (response) => {
            this.valueChange.emit(response)
        },
        (error) =>{
              this.valueChange.emit('c est une erreur')
        })
  }

}

Composant fils : ce qui est important c’est qu’on a besoin de EventEmitter et de Output. La fonction checkLogin reçoit la réponse du serveur, et en cas de succès un message est émis avec un payload (response) vers le composant parent. L’objet valueChange de type EventEmitter est décoré par @Output, ce qui a pour but de faire sortir le message du composant fils.

#template HTML Composant Parent
<ion-content>
    <div class="main-appli home" >
        <div class="content-accueil">
            <loginform (valueChange)='getLoginInfo($event)'></loginform>
        </div>
    </div>
</ion-content>

#code TS 
  getLoginInfo(response){
    //votre code pour la gestion de ce qui est renvoyé par le composant fils
  }

Dans le composant parent, le template inclue bien sûr le composant fils, et on y retrouve valueChange qui est un événement au même titre qu’un (click) qu’on voit habituellement dans Angular. Et la fonction getLoginInfo prend en paramètre un objet de type EventEmitter, ne cherchez pas à comprendre davantage, car en sous-main c’est le framework Angular qui fait les choses. Retenez simplement cette recette pour que le composant fils puisse émettre un message vers le composant parent.

Remarque sur @ViewChild

Le mécanisme @ViewChild est un peu différent de ce qu’on vient de voir, en effet, avec ce décorateur, c’est le composant parent qui est initiateur de la lecture/écriture sur le composant fils, alors qu’avec ce qu’on vient de voir c’est le composant fils qui est initiateur de l’émission d’un message, (il n’y a pas de lecture/écriture sur le composant parent).

Vous aimerez aussi...