Home > database >  How to render multiples times the same component with diferent content in angular 12
How to render multiples times the same component with diferent content in angular 12

Time:12-26

im trying to render a component that is inside a ng-for, but the content of the component will be trigger after a click on a button, the content will be captured and then sent to the child component. After that i need to render the child component using the data that i have obtained by the click. But the child component need to be render inside the same index in ng-for and not to render in all indexes of the array.

Here we can see some code:

Parent component HTML

<div >
  <div >
    <div *ngFor="let pessoa of lista; index as i" >
      <div >
        <div >
          <span > Diretor </span>
          <span > {{pessoa.nome}}</span>
        </div>
      </div>

      <div  *ngFor="let x of pessoa.filmes">
        <mat-card >
          <mat-card-header>
            <mat-card-subtitle>{{x.tipo}}</mat-card-subtitle>
            <mat-card-title>{{ x.nome}}</mat-card-title>
          </mat-card-header>
          <img mat-card-image src="{{x.imgPath}}"  alt="{{x.imgDesc}}">
            <mat-divider></mat-divider>
          <mat-card-actions>
            <button mat-button color="primary" (click)="openDetails(pessoa.id, x);" >Detalhes</button>
          </mat-card-actions>
        </mat-card>
      </div>

      <ng-container *ngIf="click">
        <app-teste2 [objFilme]="heranca"></app-teste2>
      </ng-container>

    </div>
  </div>
</div>

Parent component TS

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

@Component({
  selector: 'app-teste1',
  templateUrl: './teste1.component.html',
  styleUrls: ['./teste1.component.scss']
})
export class Teste1Component {

    lista = [
    {nome:'Beltrano', id:1,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg', nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg', nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujutsu no Kaisen',imgPath:'../../../assets/jjk.jpg', nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg', nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},

    {nome:'Fulano', id:2,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg' ,nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg' ,nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujustu no Kaisen',imgPath:'../../../assets/jjk.jpg' ,nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg' ,nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},

    {nome:'Ciclano', id:3,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg' ,nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg' ,nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujutsu no Kaisen',imgPath:'../../../assets/jjk.jpg' ,nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg' ,nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},

    {nome:'Giclano', id:4,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg' ,nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg' ,nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujutsu no Kaisen',imgPath:'../../../assets/jjk.jpg' ,nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg' ,nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},
  ]

  heranca: any
  click!: boolean
  array: any[] = []


  openDetails(id:number, filme:any){
    this.click = true
    this.heranca = {
      id_diretor:id,
      nome: filme.nome,
      tipo: filme.tipo,
      duracao: filme.duracao,
      descricao: "Filme ou série xpto"
    }
    this.saveIntoArray(this.heranca)
  }

  saveIntoArray(filme: any){
    this.array.push(filme)
    console.log(this.array)


  }


}

Child Component HTML

<mat-card>
  <mat-card-content>
    <div >

      <span >Filme:
        <span >{{filme.nome}}</span>
      </span>
      <span >Duração:
        <span >{{filme.duracao}}</span>
      </span>
      <span >Descrição:
        <span >{{filme.descricao}}</span>
      </span>
    </div>
  </mat-card-content>
</mat-card>

Child component TS

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-teste2',
  templateUrl: './teste2.component.html',
  styleUrls: ['./teste2.component.scss']
})
export class Teste2Component implements OnChanges{

@Input() objFilme:any

filme: any;


ngOnChanges(changes: SimpleChanges){
  for (const propname in changes){
    const chg = changes[propname]
    const cur = chg.currentValue
    console.log(cur);
    if (cur) {
      this.filme = cur
    }
  }


}

}

What i achived

When i click on button "detalhes" open a card on the right with the data of the selected card but it duplicate for all others lines too.

Actual Code

What i want to achive When i click on the button "detalhes" i need to open a card on the right with the selected data just for that line.

Exemple of what i want

Im already try to create a ng-for inside the container to match the main ng-for index to render just for the correct container.

CodePudding user response:

Why not creating a new, additional component that represents a row in your 'card-table'? If this new CardRowComponent contained the heranca: any-property, it would mean that every card-row can display ones own herana-value.

In my solution there would be 3 components (and possibly 1 service):

  • Teste1Component (modified)
  • CardRowComponent (new)
  • Teste2Component (unchanged)
  • Optional: A Service that contains array: any[] = [];

The CardRowComponent HTML could look like this:

<div  *ngFor="let x of filmes">
  <mat-card >
    <mat-card-header>
      <mat-card-subtitle>{{x.tipo}}</mat-card-subtitle>
      <mat-card-title>{{ x.nome}}</mat-card-title>
    </mat-card-header>
    <img mat-card-image src="{{x.imgPath}}"  alt="{{x.imgDesc}}">
      <mat-divider></mat-divider>
    <mat-card-actions>
      <button mat-button color="primary" (click)="openDetails(pessoa.id, x);" >Detalhes</button>
    </mat-card-actions>
  </mat-card>
</div>

<ng-container *ngIf="click">
  <app-teste2 [objFilme]="heranca"></app-teste2>
</ng-container>

The CardRowComponent TS would look something like this:

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

@Component({
  selector: 'app-card-row',
  templateUrl: './card-row.component.html',
  styleUrls: ['./card-row.component.scss']
})
export class CardRowComponent {

  @Input()
  filmes!: any[];

  heranca: any;
  click!: boolean;
  array: any[] = [];

  openDetails(id:number, filme:any){
    this.click = true
    this.heranca = {
      id_diretor:id,
      nome: filme.nome,
      tipo: filme.tipo,
      duracao: filme.duracao,
      descricao: "Filme ou série xpto"
    }
    this.saveIntoArray(this.heranca)
  }

  saveIntoArray(filme: any){
    this.array.push(filme)
    console.log(this.array)
  }
}

The Parent-Component HTML would look something like this:

<div *ngFor="let pessoa of lista; index as i" >
  <div >
    <div >
      <span > Diretor </span>
      <span > {{pessoa.nome}}</span>
    </div>
  </div>

 <app-card-row [filmes]="pessoa.filmes"></app-card-row>

</div>

The Parent-Component TS would just contain the movies-list:

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

@Component({
  selector: 'app-teste1',
  templateUrl: './teste1.component.html',
  styleUrls: ['./teste1.component.scss']
})
export class Teste1Component {

    lista = [
    {nome:'Beltrano', id:1,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg', nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg', nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujutsu no Kaisen',imgPath:'../../../assets/jjk.jpg', nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg', nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},

    {nome:'Fulano', id:2,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg' ,nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg' ,nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujustu no Kaisen',imgPath:'../../../assets/jjk.jpg' ,nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg' ,nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},

    {nome:'Ciclano', id:3,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg' ,nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg' ,nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujutsu no Kaisen',imgPath:'../../../assets/jjk.jpg' ,nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg' ,nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},

    {nome:'Giclano', id:4,
    filmes:[
    { imgDesc:'community',imgPath:'../../../assets/community.jpg' ,nome:'Community', tipo:'Serie',  duracao:'3:20'},
    { imgDesc:'Avatar',imgPath:'../../../assets/avatar1.jpg' ,nome:'Avatar', tipo:'Filme',  duracao:'3:20'},
    { imgDesc:'Jujutsu no Kaisen',imgPath:'../../../assets/jjk.jpg' ,nome:'Jujutsu no Kaizen', tipo:'Anime',  duracao:'3:20'},
    { imgDesc:'Kamen Rider',imgPath:'../../../assets/kmrider.jpg' ,nome:'Kamem-rider', tipo:'Dorama', duracao:'3:20'}]},
  ]
}

The current Teste2Component would remain unchanged.

Hint: Since you possibly want to have a global array: any[] = []; that is shared among all card-rows, you could move this array to a service and then inject the service into CardRowComponent via constructor.

  • Related