简体   繁体   English

有没有办法在Angular材料中使用mat-table编辑表格的特定列

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

In my project i am using Angular Material's table for displaying value in table format, As per new requirement i have to perform in-line editing for last 2 column over other along with that if user click 1st column the other column get highlighted automatically and everything has to be done using Angular material在我的项目中,我使用 Angular Material 的表格以表格格式显示值,根据新要求,我必须对最后 2 列执行在线编辑,如果用户单击第一列,另一列将自动突出显示,所有内容必须使用 Angular 材料完成

This is the last 2 column i want to perform in-line editing这是我要执行内嵌编辑的最后 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>

How i achieved is as follows :我是如何实现的如下:

<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 file for above code :上述代码的 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);
  }
}

I expect the result as table where last 2 column can be edited inline and at the same time i can send modified data to backend我希望结果为表格,其中最后 2 列可以内联编辑,同时我可以将修改后的数据发送到后端

Naman, it's the same, you need use <ng-container> to avoid create extra tags, so your columns becomes like 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>

Well, I call to function "edit" passign two arguments, the position and a string indicate the "name" of the input attributes.好吧,我调用函数“edit” passign 两个参数,位置和字符串表示输入属性的“名称”。 This allow us "focus" the input clicked.这允许我们“聚焦”点击的输入。 how?如何?

We declare a ViewChildren of the MatInputs我们声明了一个 MatInputs 的 ViewChildren

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

See that we get not the MatInput else the "ElementRef".看到我们得到的不是 MatInput 而是“ElementRef”。 This allow us, in out function edit get the element with the attributes name equal the string that pass as argument, and focus it.这允许我们在 out 函数 edit 中获取属性名称等于作为参数传递的字符串的元素,并将其聚焦。 See that we need "enclosed" all in a setTimeout to allow Angular to show the input看到我们需要在 setTimeout 中“封闭”所有内容以允许 Angular 显示输入

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

You can see the full example in stackblitz你可以在stackblitz 中看到完整的例子

Well, in the example the data is hardcoded.好吧,在示例中,数据是硬编码的。 Let's go to imagine that the data (and the structure) comes from a service data.让我们想象一下数据(和结构)来自服务数据。 The data is easy imagine because it's the same.数据很容易想象,因为它是相同的。 The "structure" we can imagine as an array of object with three properties: name,head ad fixed.我们可以将“结构”想象为具有三个属性的对象数组:名称、头部和固定。 if fixed is true, we only show the data, else we can edit.如果fixed 为true,我们只显示数据,否则我们可以编辑。 So the only thing we need is create the columns in a *ngFor所以我们唯一需要的是在 *ngFor 中创建列

First we are going to see how our schema can be defined.首先,我们将看到如何定义我们的模式。 It's only an array这只是一个数组

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

]

Our table becomes like我们的桌子变得像

<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>

See that we "replace" element.position by element[column[0].name] -I supouse the first element of the schema will be the "key" and how we using [(ngModel)]="elemen[column.name]".看到我们用 element[column[0].name] “替换” element.position - 我假设模式的第一个元素将是“键”以及我们如何使用 [(ngModel)]="elemen[column.name] ]”。 Yes, to refererd to element.position we can refered too as elemen["position"] and remember we are iterating over "schema"是的,要引用 element.position 我们也可以将其称为 elemen["position"] 并记住我们正在迭代“schema”

Another thing is that we are going to use "id", not "name".另一件事是我们将使用“id”,而不是“name”。 this is because if we using name, really Angular put as attrib some like: ng-reflect-name, and this don't allow us focus the input.这是因为如果我们使用名称,真的 Angular 会像这样放置属性:ng-reflect-name,这不允许我们关注输入。

Finally we are get the data in the ngOnInit.最后我们在 ngOnInit 中获取数据。 We are going to use forkJoin to get together the schema and the data.我们将使用 forkJoin 将模式和数据放在一起。 A forkJoin only call and array of observables (in this case this.dataService.getSchema() and this.dataServide.getData, and return in an array the response of all the observables. We use the way ([variable1,variable2]) to store in "variable1" the first result and in variable2 the second result一个 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
    })
}

The displayedColumns must be an array with the names of the columns, but we need to store in an array the "schema" too. displayColumns 必须是一个包含列名称的数组,但我们也需要将“模式”存储在一个数组中。

In the stackblitz I create a service and "simulate" the observable using the rxjs creation operator of , in a real application the data becomes from a httpClient.get(....)stackblitz我创建服务和“模拟”使用rxjs创建运营商可观察到of在实际应用从数据变为一个httpClient.get(....)

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM