1

I am experiencing some difficulties when I try to organize communication between two components in Angular.

The parent's component is "animal" and the child component is "animalEspece".

That's how my web page looks like now:

webpage-demo

When I click in a type of animal like Requin, Shark, ... I want that the child component (called animalEspece) display only this type of animal.

For that I have a list with all my animals and I give this list to the component animalEspece.

But when I click nothing happens. The component animalEspece receives the variables but nothing is displayed.

This is my animal html code :

<p scope="col" style="text-shadow:0 0 2px #ff1c1ce5,0 0 30px #ff1c1ce5,0px 0px 5px #ff1c1ce5, 0 0 150px #ff1c1ce5;color:#ff1c1ce5;
text-align: center; font-size: 25px;">Nos especes</p>
<div class="scrolling-wrapper">
  <a *ngFor="let a of especeAnimalPresente" class="animated-button1" (click)="changeEspeceChoisi(a);">
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    {{a}}
  </a>
</div>

<table class="table" style="color:white">
    <thead class="thead-dark">
      <tr>
        <th scope="col">#</th>
        <th scope="col">Espece</th>
        <th scope="col">Nom</th>
        <th scope="col">Sexe</th>
        <th scope="col">Signe distinctif</th>
        <th scope="col">Bilan de sante</th>
        <th scope="col">Date arrivee</th>
        <th scope="col">Date depart</th>
        <th scope="col">Taille</th>
        <th scope="col">Age</th>
        <th scope="col">Bassin d'appartenance</th>
        <th scope="col">supprimer</th>

      </tr>
    </thead>
    <tbody>
        <tr *ngFor="let a of animaux">
          <th scope="row">{{a.id}}</th>
          <td>{{a.espece}}</td>
          <td>{{a.nom}}</td>
          <td>{{a.sexe}}</td>
          <td>{{a.signeDistinctif}}</td>
          <td>{{a.bilanSante}}</td>
          <td>{{a.dateArr}}</td>
          <td>{{a.dateDep}}</td>
          <td>{{a.taille}}</td>
          <td>{{a.age}}</td>
          <td>{{a.bassin.id}}</td>
          <td>
            <button class="bouton17" (click)="supprimerAnimal(a.id)">
              Supprimer
            </button></td>
          <td></td>
        </tr>
      </tbody>
</table>

This my animal.ts :

import { Component, OnInit } from '@angular/core';
import { AnimalService } from "./animal.service";
import { Animal } from "./animal";
import { Bassin } from "../bassin/bassin";

@Component({
  selector: 'app-animal',
  templateUrl: './animal.component.html',
  styleUrls: ['./animal.component.css']
})
export class AnimalComponent implements OnInit {

  private nomEspece:string;
  private animaux:Array<Animal>;
  private especeAnimalPresente:Array<string>;
  private especeAnimalPresenteTmp:Array<string>;
  constructor(private animalService: AnimalService) { 
    this.especeAnimalPresenteTmp = [];
  }

  ngOnInit() {
    this.recupAllAnimals();
  }

  supprimerAnimal(id:number){
    this.animalService.deleteAnimal(id);
  }

  recupAllAnimals(){
    this.animalService.getAllAnimaux().subscribe(data => {
      this.animaux = data;
      this.recupEspecePresent();
      console.log(this.animaux);
    })

  }

  recupEspecePresent(){
     if (this.animaux){
      for (let animal of this.animaux) {
          this.especeAnimalPresenteTmp.push(animal.espece);
      }
      this.especeAnimalPresente = this.removeDuplicates(this.especeAnimalPresenteTmp);
     }
  }

  removeDuplicates(array) {
    let unique = {};
    array.forEach(function(i) {
      if(!unique[i]) {
        unique[i] = true;
      }
    });
    return Object.keys(unique);
  }

  retourneAnimal(){
    return this.animaux;
  }

  changeEspeceChoisi(a){
    alert(a);
    this.nomEspece=a;
    alert(this.nomEspece);
  }

  retourneEspece(){
    return this.nomEspece;
  }

}
    Component son :
    <br>
    <app-animalespece [animaux]=retourneAnimal() [nomEspece]=retourneEspece()></app-animalespece>
    <br>

This is my html animalEspece code :

<table class="table" style="color:white">
    <thead class="thead-dark">
      <tr>
        <th scope="col">#</th>
        <th scope="col">Espece</th>
        <th scope="col">Nom</th>
        <th scope="col">Sexe</th>
        <th scope="col">Signe distinctif</th>
        <th scope="col">Bilan de sante</th>
        <th scope="col">Date arrivee</th>
        <th scope="col">Date depart</th>
        <th scope="col">Taille</th>
        <th scope="col">Age</th>
        <th scope="col">Bassin d'appartenance</th>
      </tr>
    </thead>
    <tbody>
        <tr *ngFor="let a of listeAnimauxEspece">
          <th scope="row">{{a.id}}</th>
          <td>{{a.espece}}</td>
          <td>{{a.nom}}</td>
          <td>{{a.sexe}}</td>
          <td>{{a.signeDistinctif}}</td>
          <td>{{a.bilanSante}}</td>
          <td>{{a.dateArr}}</td>
          <td>{{a.dateDep}}</td>
          <td>{{a.taille}}</td>
          <td>{{a.age}}</td>
          <td>{{a.bassinAppartenance}}</td>
        </tr>
      </tbody>
</table>

And this is my animalEspece.ts :

import { Component, OnInit, Input } from '@angular/core';
import { Animal } from "../animal/animal";

@Component({
  selector: 'app-animalespece',
  templateUrl: './animalespece.component.html',
  styleUrls: ['./animalespece.component.css']
})
export class AnimalespeceComponent implements OnInit {

  @Input()
  private animaux:Array<Animal>;

  @Input()
  private nomEspece:string;

  private listeAnimauxEspece:Array<Animal>;

  constructor() {
    this.listeAnimauxEspece = [];
  }

  ngOnInit() {
    this.filtreAnimauxEspece();
  }

  filtreAnimauxEspece(){
    if (this.animaux){
      for (let animal of this.animaux) {
        if (animal.espece == this.nomEspece){
          this.listeAnimauxEspece.push(animal);
        }
      }
    }
  }

}

After many test I understand that the problem it was my component animalEspece is already initialized before I clic on a button. I can solve my probleme if I create a new boolean (named bool) initialized to false, but change to true when I clic on an animal button. And if I write in the animal html :

<app-animalespece *ngIf='bool' [animaux]=retourneAnimal() [nomEspece]=retourneEspece()></app-animalespece>

But this solution works only for the first click on the animal button. And I feel that it is not a good approach to solve this task.

So I need help in order to when I click in an animal button, this button displays the respective animal. And that for each click on that button.

Thank you in advance for your help.

1 Answer 1

1

What you need to do is to intercept when the input change. Your problem now is that the child component is taking an initial input, it is not checking updates of the input.

So, one way to solve your problem is to create a set function for the input. Like this,

private _nomEspece:string;
@Input()
set nomEspece(nom:string) {
  // update value
  this._nomEspece = nom;
  // update list
  this.listeAnimauxEspece = [];
  this.filtreAnimauxEspece();
}
get nomEspece():string {
  return _nomEspece;
}

Now, each time the input changes you are gonna update the value and update the list.

Angular Docs - Intercept input property changes with a setter

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you it work ! But I have other question. Now if I clic un a Requin button, all the Requin are displayed. But then, if I clic in Tortue button, all my Requin and all my Tortue are displayed. How can I reset my list after (or before) each clic ?
I just edit the answer, basically you just need to restart the list, check the line before calling filtreAnimauxEspece
Thank you very much for all your answer !
Glad it help you!!.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.