Passar um objeto ou um atributo de component htmt angular para um Dialog angular Material

Caros, estou com este problema: Eu consigo trazer do banco atravez do "*ngFor=“let produto of produtos” " , desenha tudo bonitinho la no card do material (nome, valor, quantidade, foto…vindos do banco). Consegui colocar neste mesmo component htmt o iframe com uma string do link do youtube (usei as classe necessárias para isso). O problema é que eu não quero este video nesta tela, eu quero poder click em um botão e abrir um Dialog Material e lá colocar este video. eu não consigo passar o objeto produto para o Dialog. Como faço isso?

Queria que o meu “produto.urlSafe” fosse aceito la no meu dialog-show-video.component.html

Isto não funciona lá:

                <mat-card-content fxLayoutAlign="center center">
                    <div>
                      <iframe width="560" height="315" [src]="produto.urlSafe" frameborder="0" 
                          allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in- 
                             picture" allowfullscreen></iframe>
                    </div>
                 </mat-card-content>

Alguma dica?

Penso que, do jeito que vc fez, é preciso ter essa variável produto declarada no componente desse template. E essa variável precisaria ser preenchida com o item selecionado no momento do clique.


Outra forma, seria separar esse iframe num componente separado, e receber o produto como @Input. Veja: https://angular.io/guide/component-interaction

Este usando o @input() valor : any , eu tentei… mas acho que por causa do *ngFor da erro.

Posta ai como está o seu ngFor.

<mat-tab-group style="padding-top: 0px; padding-left: 2%; padding-right: 2%;">
  <mat-tab label="Venda Varejo">
    <div fxLayout="row" fxLayoutAlign="start start">
      <ng-container *ngFor="let produto of produtos" style="margin: 0.5%;">
        <!-- tentei colocar aqui -->
        <app-dialog-show-video [link]="produto.urlSafe"></app-dialog-show-video>
        
        <mat-card class="mat-card-live" fxFlex="0 1 calc(33.3% - 11px)" fxFlex.lt-md="0 1 calc(50% - 11px)" fxFlex.lt-sm="100%">
          <mat-card-header>
            <mat-card-title><strong>{{produto.nome}}</strong></mat-card-title>
            <mat-card-subtitle>Preço: R$ <strong>{{produto.valor}}</strong></mat-card-subtitle>
            <mat-card-subtitle>Qtde em estoque: <strong>{{produto.quantidade}}</strong></mat-card-subtitle>
            
            <div>
              <button style="font: size 0.1rem; height: 30px; margin: 2px;" mat-raised-button>
                Editar
              </button>
              
              <button style="font: size 0.1rem; height: 30px;  margin: 2px; color: red;" mat-raised-button>
                Excluir
              </button>
              
              <br>
              
              <button ng (click)="verVideo()" style="font: size 0.1rem; height: 30px; margin: 2px;" mat-raised-button>
                Vídeo
              </button>
              
              <button style="font: size 0.1rem; height: 30px; margin: 2px;" mat-raised-button>
                Pedido
              </button>
            </div>
          </mat-card-header>
          
          <img class="example-header-image" src={{produto.foto}} alt="Photo of a Shiba Inu">
          
          <mat-card-content fxLayoutAlign="center center">
            <div>
              <iframe width="560" height="315" [src]="produto.urlSafe" frameborder="0"
                allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
                allowfullscreen>
              </iframe>
            </div>
          </mat-card-content>
          
          <mat-card-actions>

          </mat-card-actions>
        </mat-card>
      </ng-container>
    </div>
  </mat-tab>
  
  <mat-tab label="Vendas atacado">
    <div fxLayout="row" fxLayoutAlign="start center" style="padding: 2%">
      <div style="margin: 0.5%;">
        <mat-card class="mat-card-live" fxFlex="0 1 calc(33.3% - 11px)" fxFlex.lt-md="0 1 calc(50% - 11px)" fxFlex.lt-sm="100%">
          <mat-card-header>

          </mat-card-header>
          
          <mat-card-content>
            <p>Em manutenção</p>
          </mat-card-content>
        </mat-card>
      </div>
    </div>
  </mat-tab>
  
  <mat-tab label="Vendas Propostas ">
    <div fxLayout="row" fxLayoutAlign="start center" style="padding: 2%">
      <div style="margin: 0.5%;">
        <mat-card class="mat-card-live" fxFlex="0 1 calc(33.3% - 11px)" fxFlex.lt-md="0 1 calc(50% - 11px)" fxFlex.lt-sm="100%">
          <mat-card-header>

          </mat-card-header>
          
          <mat-card-content>
            <p>Em manutenção</p>
          </mat-card-content>
        </mat-card>
      </div>
    </div>
  </mat-tab>
</mat-tab-group>

Classe filha

import { Component, OnInit,Input } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { ProdutoService } from 'src/app/shared/service/produto.service';

@Component({
  selector: 'app-dialog-show-video',
  templateUrl: './dialog-show-video.component.html',
  styleUrls: ['./dialog-show-video.component.css']
})
export class DialogShowVideoComponent implements OnInit {
  
  @Input() link : any;
  
  constructor(
    public dialogRef: MatDialogRef<DialogShowVideoComponent>
  ) {}
  
  ngOnInit(): void {}
  
  fechar(): void {
    this.dialogRef.close();
  }
}

Quando verifico o inspecionar do navegador (console) tem:

core.mjs:24833 Angular is running in development mode. Call enableProdMode() to enable production mode.
produto-list.component.ts:53 ProdutoService
core.mjs:6461 ERROR NullInjectorError: R3InjectorError(AppModule)[MatDialogRef -> MatDialogRef -> MatDialogRef]: 
  NullInjectorError: No provider for MatDialogRef!
    at NullInjector.get (core.mjs:11095:1)
    at R3Injector.get (core.mjs:11262:1)
    at R3Injector.get (core.mjs:11262:1)
    at R3Injector.get (core.mjs:11262:1)
    at NgModuleRef.get (core.mjs:21807:1)
    at Object.get (core.mjs:21484:1)
    at lookupTokenUsingModuleInjector (core.mjs:3334:1)
    at getOrCreateInjectable (core.mjs:3446:1)
    at Module.ɵɵdirectiveInject (core.mjs:14381:1)
    at NodeInjectorFactory.DialogShowVideoComponent_Factory [as factory] (dialog-show-video.component.ts:15:38)
defaultErrorLogger @ core.mjs:6461
index.js:548 [webpack-dev-server] Live Reloading enabled.

Acho que vc só precisa renderizar um <app-dialog-show-video />. E ir mudando na medida em que o produto for escolhido para ter o vídeo apresentado.

Tente tirar o <app-dialog-show-video /> do ngFor. E cria uma variável, ex.: produtoSelecionado, para receber o produto que terá o vídeo apresentado.

Já o componente do vídeo, vc terá que controlar o momento em que ele irá aparecer. Talvez ele tenha alguma varíavel que indica se ele deve estar aberto (visível) ou não.

O componente de vídeo irá usar a variável do produto selecionado que vc criou:

<app-dialog-show-video [link]="produtoSelecionado.urlSafe" [open]="open"></app-dialog-show-video>

E no botão de “verVideo”, vc passa o produto como parâmetro e atribui na variavel produtoSelecionado, e marca a variável open como true.

Consegui passar a ideia? Tenta fazer assim pra ver se funciona.

Reparei que vc tem usado any nos tipos. Se puder, evite ao máximo isso, pq deixa seu código frágil. Melhor definir os tipos e usá-los.

Tava pensando em usar o método que busca o produto por Id. Quando eu clickar no botão o método receber o id … Será que daria certo assim?

Mas no ngFor vc já tem o produto completo, não?

sim

Então não precisa recuperar o produto pelo ID de novo, basta atribuir o produto na variável do componente que está referenciada na declaração do componente de vídeo:

<app-dialog-show-video [link]="produtoSelecionado.urlSafe" [open]="open"></app-dialog-show-video>
                                       ^