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:
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.
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