【问题标题】:Angular Material - Get value of one column for a mat-table using a serviceAngular Material - 使用服务获取 mat-table 的一列的值
【发布时间】:2021-06-18 13:48:48
【问题描述】:

情况

我有一张表,里面填满了来自接口 A 的数据。但是其中一列应该根据接口 A 的 id 填充接口 B 的过滤数据。

我尝试了什么

html:

<mat-table [dataSource]="dataSource">
    ...
    <ng-container matColumnDef="title">
        <mat-header-cell *matHeaderCellDef> Title</mat-header-cell>
        <mat-cell *matCellDef="let element"> {{getValueOfInterfaceB(element.id)}} </mat-cell>
    </ng-container>
    ...
</mat-table>

ts:

getValueOfInterfaceB(id: number){
    let filter: any = {Id: id}
    this.entrieService.getEntries(filter).subscribe((entries: Entry[]) => {
        console.log(entries);
    })
}

问题

如果我运行应用程序,这些行将反复执行。如果我不想一遍又一遍地运行代码,我将如何解决这个问题?


编辑:尝试@Eliseo 解决方案时出错

error TS2304: Cannot find name 'res'.
res[] => {

error TS1011: An element access expression should take an argument.
res[] => {

error TS1005: ',' expected.
res[] => {

error TS18004: No value exists in scope for the shorthand property 'res'. Either declare one or provide an initializer.
res.forEach((value,index)=>{

error TS2769: No overload matches this call.
res.forEach((value,index)=>{

【问题讨论】:

    标签: angular typescript angular-material angular-services


    【解决方案1】:

    向对象数组添加新属性比在 .html 中调用函数要好。如果“计算列”来自 API,您应该创建一个订阅数组(使用 map)并使用 forkJoin 订阅 obs 数组

    我想你有一个数据数组[{Id:0},{Id:1}....]

    你做了类似的东西

    //create an array of obs
    const obs$[]=this.dataarray.map(x=>this.entrieService.getEntries({Id:x.id})
    //subscribe to forkJoin
    forkJoin(obs).subscribe(res[]=>{
        //in res[0] you has the response to this.entrieService.getEntries({Id:0})
        //in res[1] you has the response to this.entrieService.getEntries({Id:1})
        ...
        //so you can iterate using forEach and index and make some like
        res.forEach((value,index)=>{
            this.dataarray[index].newProperty=value
        })
    }
    

    然后创建数据源。请记住,如果您有一个复杂的“列计算”,请在 ngOnInit 中只计算一次该列

    【讨论】:

    • 感谢您的快速回复。我尝试将其用作解决方案,但是当我尝试实现代码示例时,我会得到您可以在我的初始帖子中看到的添加的问题。我错过了什么?
    • 对不起,是subscribe((res:any[])=&gt;{...})
    • 我选择了这个解决方案,它也帮助我解决了另一个问题。非常感谢。
    【解决方案2】:

    你可以这样做:

    entries: Entry[] = [];
    getValueOfInterfaceB(id: number){
       if (this.entries.length)
            return entries;
    
        let filter: any = {Id: id}
        this.entrieService.getEntries(filter).subscribe((entries: Entry[]) => {
           this.entries = entries;
            console.log(entries);
        })
    }
    

    此外,您可以在 html 中添加异步管道

    <mat-table [dataSource]="dataSource">
        ...
        <ng-container matColumnDef="title">
            <mat-header-cell *matHeaderCellDef> Title</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{getValueOfInterfaceB(element.id) | async }} </mat-cell>
        </ng-container>
        ...
    </mat-table>
    

    【讨论】:

    • 感谢您的快速回复。也许我没有完全理解它,但在提到的示例中,条目将是数据源的第一个元素的字段,此后不会再为任何其他元素调用,因为 'if(this.entries.length)' 将是总是正确的。还是我理解错了?
    • if(this.entries.length) 用于从服务/异步调用中获取数据一次。如果您希望在每次迭代中更新数据,这完全是可选的。
    猜你喜欢
    • 2019-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多