簡體   English   中英

有沒有辦法在Angular材料中使用mat-table編輯表格的特定列

[英]Is there any way to edit specific Column of table using mat-table in Angular material

在我的項目中,我使用 Angular Material 的表格以表格格式顯示值,根據新要求,我必須對最后 2 列執行在線編輯,如果用戶單擊第一列,另一列將自動突出顯示,所有內容必須使用 Angular 材料完成

這是我要執行內嵌編輯的最后 2 列

>  <ng-container matColumnDef="weight">
>       <th mat-header-cell *matHeaderCellDef> Weight </th>
>       <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
>     </ng-container>
>     <ng-container matColumnDef="symbol">
>       <th mat-header-cell *matHeaderCellDef> Symbol </th>
>       <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
>     </ng-container>
>   
>     
>     <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
>     <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>   </table>

我是如何實現的如下:

<tbody>
                <tr *ngFor="let data of dataSource">      
                   <td >{{data.position}}</td>
                   <td >{{data.name}}</td>
                   <td *ngIf="data.position === editRowId"> <input matInput [(ngModel)]="data.weight"></td>
                   <td *ngIf="data.position !== editRowId" (click)="editTableRow(data.position)">{{data.weight}}</td>
                   <td *ngIf="data.position === editRowId"> <input matInput [(ngModel)]="data.symbol"></td>
                   <td *ngIf="data.position !== editRowId" (click)="editTableRow(data.position)">{{data.symbol}}</td>
                </tr>
            </tbody>

上述代碼的 TS 文件:

export class AppComponent {
  showEditTable = false;
  editRowId: any = '';
  selectedRow;
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = ELEMENT_DATA;
  editTableRow(val) {
  console.log('click event started val = ' + val);
  this.editRowId = val;
  console.log('click event ended with val = ' + val);
  }
}

我希望結果為表格,其中最后 2 列可以內聯編輯,同時我可以將修改后的數據發送到后端

Naman,是一樣的,你需要使用<ng-container>來避免創建額外的標簽,所以你的列變得像

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef> Weight </th>
    <td mat-cell *matCellDef="let element"> 
      <ng-container *ngIf="element.position!==editRowId">
      <span (click)="edit(element.position,'weigth')">{{element.weight}} </span>
      </ng-container>
      <ng-container *ngIf="element.position===editRowId">
      <input matInput name="weigth" [(ngModel)]="element.weight"> 
      </ng-container>
      </td>
  </ng-container>

好吧,我調用函數“edit” passign 兩個參數,位置和字符串表示輸入屬性的“名稱”。 這允許我們“聚焦”點擊的輸入。 如何?

我們聲明了一個 MatInputs 的 ViewChildren

  @ViewChildren(MatInput,{read:ElementRef}) inputs:QueryList<ElementRef>;

看到我們得到的不是 MatInput 而是“ElementRef”。 這允許我們在 out 函數 edit 中獲取屬性名稱等於作為參數傳遞的字符串的元素,並將其聚焦。 看到我們需要在 setTimeout 中“封閉”所有內容以允許 Angular 顯示輸入

  edit(row,element)
  {
    this.editRowId=row;
    setTimeout(()=>{
      this.inputs.find(x=>x.nativeElement.getAttribute('name')==element)
          .nativeElement.focus()
    })
  }

你可以在stackblitz 中看到完整的例子

好吧,在示例中,數據是硬編碼的。 讓我們想象一下數據(和結構)來自服務數據。 數據很容易想象,因為它是相同的。 我們可以將“結構”想象為具有三個屬性的對象數組:名稱、頭部和固定。 如果fixed 為true,我們只顯示數據,否則我們可以編輯。 所以我們唯一需要的是在 *ngFor 中創建列

首先,我們將看到如何定義我們的模式。 這只是一個數組

[
   {name:'position',head:"No.",fixed:true},
   {name:'name',head:"Name",fixed:true},
   {name:'weight',head:"Weigth",fixed:false},
   {name:'symbol',head:"Symbol",fixed:false},

]

我們的桌子變得像

<table #table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
    <ng-container *ngFor="let column of schema;let last=last">
        <ng-container [matColumnDef]="column.name">
            <th mat-header-cell *matHeaderCellDef> {{column.head}} </th>
            <td mat-cell *matCellDef="let element">
                <ng-container *ngIf="element[schema[0].name]!==editRowId || column.fixed">
                    <span 
                      (click)="column.fixed?editRowId=-1:
                               edit(element[schema[0].name],column.name)">
                         {{element[column.name]}} 
                    </span>
      </ng-container>
      <ng-container *ngIf="element[schema[0].name]===editRowId && !column.fixed">
         <input matInput [id]="column.name"
              [(ngModel)]="element[column.name]"
              (blur)="last?editRowId=-1:null"> 
      </ng-container>
      </td>
    </ng-container>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

看到我們用 element[column[0].name] “替換” element.position - 我假設模式的第一個元素將是“鍵”以及我們如何使用 [(ngModel)]="elemen[column.name] ]”。 是的,要引用 element.position 我們也可以將其稱為 elemen["position"] 並記住我們正在迭代“schema”

另一件事是我們將使用“id”,而不是“name”。 這是因為如果我們使用名稱,真的 Angular 會像這樣放置屬性:ng-reflect-name,這不允許我們關注輸入。

最后我們在 ngOnInit 中獲取數據。 我們將使用 forkJoin 將模式和數據放在一起。 一個 forkJoin 只調用一個 observables 數組(這里是 this.dataService.getSchema() 和 this.dataServide.getData,並在一個數組中返回所有 observables 的響應。我們使用 ([variable1,variable2]) 的方式將第一個結果存儲在“變量 1”中,將第二個結果存儲在變量 2 中

ngOnInit()
{
  forkJoin([this.dataService.getSchema(),this.dataService.getData()])
    .subscribe(([schema,data])=>{
      this.dataSource=data;
      this.displayedColumns=schema.map(x=>x.name)
      this.schema=schema
    })
}

displayColumns 必須是一個包含列名稱的數組,但我們也需要將“模式”存儲在一個數組中。

stackblitz我創建服務和“模擬”使用rxjs創建運營商可觀察到of在實際應用從數據變為一個httpClient.get(....)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM