Вложенный Mat-стол при нажатии на конкретную строку - PullRequest
1 голос
/ 26 марта 2019

У меня есть источник данных для mat-table после привязки, когда я нажимаю на определенную строку, мне нужно вызвать конкретный API через угловую службу и снова связать данные с datasource1 и связать его с новой mat-таблицей внутри старого матаТаблица, похожая на вложенную таблицу mat, я остановился на том, как создать несколько источников данных, потому что я не знаю, сколько кликов будет сделано конечным пользователем, щелчок определенной строки зависит от флага, который находится внутри источника данных.Мне нужно создать столько источников данных, зависит от клика или есть лучший способ?

Директива для хоста, перечисляющая событие щелчка и переключение данных: я создал директиву и смог связать простое текстовое сообщение при щелчке по определенной строке.

Я отключил событие щелчка для mat-таблица строки, если флаг y

Ожидаемый результат: -мат-таблица с несколькими строками при нажатии на конкретную строку, новая таблица-таблица шоукд прикрепляется чуть ниже строки, по которой щелкнули, и так далее

Мой вид Расположение Компонент: -

  <mat-table *ngIf="showTable" #table [dataSource]="dataSource">

    <ng-container *ngFor="let header of displayedColumns;index as i" [matColumnDef]="header">
      <mat-header-cell *matHeaderCellDef>{{header}} </mat-header-cell>
      <ng-container *ngIf=" header!='Action' ">
        <mat-cell *matCellDef="let element"> {{element[header]}} </mat-cell>
      </ng-container>
      <ng-container *ngIf=" header=='Action' ">
        <mat-cell *matCellDef="let row">
          <mat- icon(click)="
          openMoveLocation(controls.selectBu.value,controls.selectLevel.value
          ,controls.selectLocation.value)">
            redo</mat-icon>
            <mat-icon (click)="openDeleteLocation()">delete</mat-icon>
            <mat-icon (click)="openDeleteTeritory()">delete_forever</mat-icon>
        </mat-cell>
      </ng-container>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;" matRipple class="element-row" [cdkDetailRow]="row" [cdkDetailRowTpl]="tpl" (toggleChange)="onToggleChange($event)">
    </mat-row>
  </mat-table>

</div>

<ng-template #tpl let-element>
  <div class="mat-row" [@detailExpand] style="overflow: hidden">
    <mat-table *ngIf="showTable" #table [dataSource]="dataSource1">

      <ng-container *ngFor="let header of displayedColumns;index as i" [matColumnDef]="header">
        <mat-header-cell *matHeaderCellDef>{{header}} </mat-header-cell>
        <ng-container *ngIf=" header!='Action' ">
          <mat-cell *matCellDef="let element"> {{element[header]}} </mat- cell>
        </ng-container>
        <ng-container *ngIf=" header=='Action' ">
          <mat-cell *matCellDef="let row">
            <mat-icon (click)="openMoveLocation
            (controls.selectBu.value,
             controls.selectLevel.value,
              controls.selectLocation.value)">
              redo</mat-icon>
            <mat-icon (click)="openDeleteLocation()">delete</mat-icon>
            <mat-icon (click)="openDeleteTeritory()">delete_forever
            </mat-icon>
          </mat-cell>
        </ng-container>
      </ng-container>

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns;" matRipple class="element-row" [cdkDetailRow]="row" [cdkDetailRowTpl]="tpl" (toggleChange)="onToggleChange($event)">
      </mat-row>
    </mat-table>
  </div>
</ng-template>

Подробная директива строки: -

import {Directive, EventEmitter, HostBinding, HostListener, Input, Output, 
    TemplateRef, ViewContainerRef, Injector} from '@angular/core';
import { LocationService } from '../../services/location/location.service'

@Directive({
  selector: '[cdkDetailRow]'
})

export class CdkDetailRowDirective {
  private row: any;
  private tRef: TemplateRef < any > ;
  private opened: boolean;

  @HostBinding('class.expanded')
  get expended(): boolean {
    return this.opened;
  }

  @Input()
  set cdkDetailRow(value: any) {
    if (value !== this.row) {
      this.row = value;
      // this.render();
    }
  }

  @Input('cdkDetailRowTpl')
  set template(value: TemplateRef<any>) {
    if (value !== this.tRef) {
      this.tRef = value;
    }
  }

  @Output() toggleChange = new EventEmitter<CdkDetailRowDirective>();

  constructor(public vcRef: ViewContainerRef) {}

  @HostListener('click')
  onClick(): void {
    if (this.row.FLAG != 'Y' && this.row.CNT != 'Y') {
      this.toggle();
    }
  }

  toggle(): void {
    if (this.opened) {
      this.vcRef.clear();
    } else {
      this.render();
    }
    this.opened = this.vcRef.length > 0;
    this.toggleChange.emit(this);
  }

  private render(): void {
    this.vcRef.clear();
    if (this.tRef && this.row) {
      this.vcRef.createEmbeddedView(this.tRef, {
        $implicit: this.row
      });
    }
  }
}

Мой вид-location.ts: -

onToggleChange(cdkDetailRow: CdkDetailRowDirective): void {

  this.requestParameters.ACTION = '0';
  this.requestParameters.BUCODE = this.controls.selectBu.value.CMPSEQNO;
  this.requestParameters.GEOLOCCODE = cdkDetailRow['row'].LOC_CODE;
  console.log(this.requestParameters)
  //call api through service and bind data to new data source but do i 
  // need to create 5 data source if user click 5 times 
  if (this.openedRow && this.openedRow.expended) {
    this.openedRow.toggle();
  }
  this.openedRow = cdkDetailRow.expended ? cdkDetailRow : undefined;
}

ОжидаетсяРезультат: -

см. Изображение 1 простая таблица матов с несколькими данными, которых я достиг

см. Изображение 2 после нажатия на любую строку, вызов API должени новая таблица матов должна быть привязана чуть ниже строки щелчка

см. изображение 3 вложенная сетка после щелчка по внутренней таблице матов

...