有什么方法可以使用Angular材质中的mat-table编辑表的特定列 [英] Is there any way to edit specific Column of table using mat-table in Angular material

查看:51
本文介绍了有什么方法可以使用Angular材质中的mat-table编辑表的特定列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我正在使用Angular Material的表格以表格格式显示值,根据新要求,我必须对最后两列进行内联编辑,如果用户单击第一列,则必须进行内联编辑.列会自动突出显示,并且所有操作都必须使用Angular材质

这是我要执行在线编辑的最后2列

This is the last 2 column i want to perform in-line editing

>  <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文件:

TS file for above code :

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

推荐答案

Naman,也是一样,您需要使用<ng-container>以避免创建额外的标签,因此您的列将变成

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

  <!-- 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"传递了两个参数,位置和字符串指示输入属性的名称".这使我们可以集中"所单击的输入.怎么样?

Well, I call to function "edit" passign two arguments, the position and a string indicate the "name" of the input attributes. This allow us "focus" the input clicked. how?

我们声明MatInputs的ViewChildren

We declare a ViewChildren of the MatInputs

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

看到我们没有得到MatInput,而是得到了"ElementRef".这允许我们在out函数编辑中获取属性名称等于作为参数传递的字符串的元素,并对其进行聚焦.看到我们需要在setTimeout中全部封闭"以允许Angular显示输入

See that we get not the MatInput else the "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. See that we need "enclosed" all in a setTimeout to allow Angular to show the input

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

您可以在 stackblitz <中看到完整的示例/a>

You can see the full example in stackblitz

在示例中,数据是硬编码的.让我们想象一下数据(和结构)来自服务数据.数据很容易想象,因为它是相同的.我们可以将结构"想象成具有三个属性的对象数组:名称,固定的标题.如果fixed为true,则仅显示数据,否则可以编辑.因此,我们唯一需要的是在* ngFor

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. So the only thing we need is create the columns in a *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},

]

我们的桌子变得像

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

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]". Yes, to refererd to element.position we can refered too as elemen["position"] and remember we are iterating over "schema"

另一件事是,我们将使用"id",而不是"name".这是因为如果我们使用name,实际上Angular会像ng-reflect-name这样将attrib放置为attrib,这不允许我们集中输入.

Another thing is that we are going to use "id", not "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.

最后,我们在ngOnInit中获取数据.我们将使用forkJoin将架构和数据整合在一起.只使用forkJoin调用和可观察对象数组(在本例中为this.dataService.getSchema()和this.dataServide.getData,然后在数组中返回所有可观察对象的响应.我们使用 ([variable1,variable2])将第一个结果存储在"variable1"中,将第二个结果存储在variable2中

Finally we are get the data in the ngOnInit. We are going to use forkJoin to get together the schema and the data. 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

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

displayedColumns必须是带有列名的数组,但是我们也需要在数组中存储模式".

The displayedColumns must be an array with the names of the columns, but we need to store in an array the "schema" too.

stackblitz 中我创建了一个服务,并使用rxjs创建运算符of模拟"了可观察对象,在实际应用程序中,数据来自httpClient.get(....)

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(....)

这篇关于有什么方法可以使用Angular材质中的mat-table编辑表的特定列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆