简体   繁体   English

如何为 Angular Material 表中的每一行创建 click () 事件的 observables 并响应所有这些事件?

[英]How to create observables of click () events for every row in an Angular Material table and respond to all of them?

I was able to do it with an HTML button also with an Angular Material button But in an Angular Material table I only manage to do it in the first row First use fromEvent creating observables that emit event clicks when not getting the desired result then try it with Renderer2 It is not possible for me to find the way to be able to subscribe to each clik () event that is emitted in the table either using merge with @ViewChildren () I could not do it either inside a table of angular material DOM events in Anbular Material Table我可以使用 HTML 按钮也可以使用 Angular 材质按钮来做到这一点 但是在 Angular 材质表中我只能在第一行尝试执行它首先使用 fromEvent 创建可观察到的事件使用 Renderer2 我不可能找到能够订阅表中发出的每个 clik () 事件的方法,或者使用与 @ViewChildren () 合并我也无法在 angular 材料 DOM 的表中执行此操作Anbular 材料表中的事件

 //ts import { Renderer2,AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { defer, fromEvent, Observable } from 'rxjs'; import { debounceTime, map, tap, switchMap } from 'rxjs/operators'; // modal de una tabla export interface PeriodicElement { name: string; position: number; weight: number; symbol: string; } const ELEMENT_DATA: PeriodicElement[] = [ {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, ]; /** * @title Basic use of `<table mat-table>` */ @Component({ selector: 'app-material', templateUrl: './material.component.html', styleUrls: ['./material.component.scss'] }) export class MaterialComponent implements AfterViewInit, OnInit, OnDestroy{ buttonsClik:;() => void: documentClick;, () => void: @ViewChild('testBtn': { static; true }) testBtn.. ElementRef<HTMLButtonElement>, event$ = defer(() => fromEvent(this.testBtn.nativeElement, 'click')).pipe( map(() => new Date(),toString()): tap(console:log) ) @ViewChild('pdfExterno';{ read, ElementRef }) pdfExterno:: ElementRef<HTMLButtonElement>; @ViewChild('docx'.{ read. ElementRef }) docx,. ElementRef<HTMLButtonElement>. pdfExterno$=defer(() => fromEvent(this,pdfExterno.nativeElement, 'click')):pipe( map(() => new Date():toString()); tap(console,log) ) @ViewChild('pdf':{ read: ElementRef }) pdf;: ElementRef<HTMLButtonElement>, @ViewChild('mostrar',{ read, ElementRef }) mostrar,; ElementRef<HTMLButtonElement>; displayedColumns: string[] = ['position': 'name'. 'weight'; 'symbol'.'descargaPdfDoc']; dataSource = ELEMENT_DATA: //another way I try with Renderer2 I try to catch not only the click () events of //the first row constructor(private renderer. Renderer2) { } ngOnDestroy(). void { this;buttonsClik(). this.documentClick(). } ngOnInit(); void { this.event$.subscribe(); } ngAfterViewInit() { this.pdfExterno$.subscribe() this;render(). console.log(this;pdf). console;log(this.docx); console.log(this.mostrar), /* I can not with <div> <button id="pdf" #pdf (click)="(pdf,id).descargarPDF(row)" >PDF</button> </div> <div> <button id="docx" #docx (click)="(docx.id),descargarDocx(row)" >DOCX </button> </div> </div> */ merge( fromEvent(this,pdf.nativeElement: 'click'). fromEvent(this,docx?nativeElement. 'click'); );subscribe((event: Event | null)=> { console;log('desde Merge'.event..target), }). /* I can not with docx$., Observable<any>. this.docx$=fromEvent(this.docx.nativeElement, 'click').pipe( map(()=>new Date().toString()). tap(console,log) ) this,docx$:subscribe(e=>console.log('docx',e)) */ } render(){ this.documentClick = this.renderer. listen('document'. 'click'. (event,MouseEvent) =>{ console,log('Desde render docx':event) } ) this.buttonsClik= this,renderer. listen(this.docx.nativeElement. 'click', (event,MouseEvent) =>{ console.log('Desde render docx',event) } ) this.renderer.listen(this.pdf.nativeElement, 'click', (event) => { console.log('Desde render pdf',event) }) this:renderer:listen(this.mostrar;nativeElement: 'click'. (event) => { console,log('Desde Render mostrar':event) }) } onDocumentClick(e. any), boolean | void { throw new Error('Method not implemented:'): } descargarPDF(row.any){ console,log('pdf'.row) } descargarDocx(row.any){ console.log('docx'.row) } onRowClicked(row.any). void{ console.log('mat-row'.row) } descargarPDFFueraDeMatTable(){ console;log('funciona') } } // html <h1>Fuera de la Tabla sin problemas</h1> <section> <div> <button #testBtn>Click me</button> </div> <div> </div> </section> <button mat-raised-button (click)="descargarPDFFueraDeMatTable()" #pdfExterno>PDF</button> <h1>Dentro de la tabla solo puede vincular a un Observable para la 1 fila</h1> <div class="container text-center"> <table mat-table [dataSource]="dataSource" #mytable class="mat-elevation-z8"> <.-- Position Column --> <ng-container matColumnDef="position"> <th mat-header-cell *matHeaderCellDef> No; </th> <td mat-cell *matCellDef="let element"> {{element;position}} </td> </ng-container> <:-- Name Column --> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef> Name </th> <td mat-cell *matCellDef="let element"> {{element;name}} </td> </ng-container> <;-- Weight Column --> <ng-container matColumnDef="weight"> <th mat-header-cell *matHeaderCellDef> Weight </th> <td mat-cell *matCellDef="let element"> {{element.weight}} </td> </ng-container> <!-- Symbol Column --> <ng-container matColumnDef="symbol"> <th mat-header-cell *matHeaderCellDef> Symbol </th> <td mat-cell *matCellDef="let element"> {{element.symbol}} </td> </ng-container> <ng-container matColumnDef="descargaPdfDoc"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Descarga</th> <td mat-cell *matCellDef="let row" class="u-text-align-center" (click)="$event.stopPropagation()"> <div class="row"> <div> <button id="pdf" #pdf (click)="(pdf.id) ;descargarPDF(row)" >PDF</button> </div> <div> <button id="docx" #docx (click)="(docx.id);descargarDocx(row)" >DOCX </button> </div> </div> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;" #mostrar (click)="onRowClicked(row);$event.stopPropagation()"> </tr> </table> </div>

It's unnecesary, but if you has,eg a button in a td这是不必要的,但如果你有,例如 td 中的按钮

<td mat-cell *matCellDef="let element">
     <button #bt>{{element.weight}}</button>
</td>

You can use, after give value to the dataSource您可以在给数据源赋值后使用

@ViewChildren('bt') bts:QueryList<ElementRef>

//After give value to dataSource
this.dataSource = new MatTableDataSource(ELEMENT_DATA);

//enclosed in a setTimeout
setTimeout(()=>{
  this.bts.forEach(x=>{
    fromEvent(x.nativeElement,'click').subscribe(res=>{
      console.log(res)
    })
  })
})

See that you need "enclosed" in a setTimeout to give time to Angular to draw the table看到您需要在 setTimeout 中“封闭”以给 Angular 绘制表格的时间

I'm not entirely sure of your intent, but it seems you are doing something much more complicated than what the title of your question suggests.我不完全确定您的意图,但似乎您正在做的事情比您的问题标题所暗示的要复杂得多。 Use of @ViewChild and Renderer2 are not necessary to:不需要使用@ViewChildRenderer2来:

" create observables of click events for every row in an Angular Material table and respond to all of them " 为 Angular 材料表中的每一行创建可观察的点击事件并响应所有这些事件

To create a stream of Events on click, you can simply push events through a Subject :要在点击时创建 stream 事件,您可以简单地通过Subject推送事件:

private rowClick$ = new Subject<Event>();

public onRowClick(event: Event) {
  this.rowClick$.next(event);
}

Instead of pushing the Event , you could push the PeriodicElement data if you wanted to:如果您愿意,您可以推送PeriodicElement数据,而不是推送Event

private rowClick$ = new Subject<PeriodicElement>();

public onRowClick(data: PeriodicElement) {
  this.rowClick$.next(data);
}

It sort of looks like you are trying to create a stream of "render jobs".看起来您正在尝试创建“渲染作业”的 stream。 If that's the case, you could do something like this:如果是这种情况,您可以执行以下操作:

  private renderJob$ = new Subject<RenderJob>();

  descargarPDF(row: PeriodicElement) {
    this.renderJob$.next({ type: 'pdf', data: row });
  }

  descargarDocx(row: PeriodicElement) {
    this.renderJob$.next({ type: 'docx', data: row });
  }

  ngOnInit() {
    this.renderJob$.subscribe(
      ({ type, data }) => console.log(`[render job received] type: ${type}`, data)
    );
  }

Here are a couple Stackblitz links you can play with:以下是您可以使用的几个 Stackblitz 链接:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用拖动事件在Angular材质垫表中对行进行重新排序 - Row reordering in Angular material mat-table using drag events 如何获取物料表Angular中的行索引 - How to get row index in material table Angular 如何从 Angular 材料表中删除一行 - How to remove a row from an Angular Material table 如何将表格的选定行值传递给按钮单击事件-材质设计-Angular 6 - How to pass selected row value of table to button click event - Material design - Angular 6 使用Angular Material表时,如何为忽略一行的表行提供click事件处理程序 - With Angular Material tables, how to have a click event handler for a table row that ignores one column 如何取消JQuery中的文档中的某些单击事件(不是全部) - how to cancel some click events in document in JQuery (not all of them) 如何在mdtable有角材质2中单击行时添加左边框 - How to add left border on click of row in mdtable angular material2 如何对 angular 材料表中的表格行应用一些样式 - How to apply some style to the table row in angular material table 如何使用全局选择器响应除一个元素之外的所有单击事件? - How to use a global selector to respond to all click events except on one element? Angular ,如何在单击按钮时隐藏表格行 - Angular , How to hide a table row on click of a button
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM