Angular Material table expandable table row not expanding?

两盒软妹~` 提交于 2020-01-05 08:37:09

问题


I've been staring at this for too long, and I can't figure it out.

There's a good example of an Angular Material table with an expandable row in this stackoverflow answer. I can plug the example into my app, and it works correctly.

I'm failing to apply the example to my data. I think my problem is in the HTML, since the table renders, the expanded row CSS seems to get applied (the row delineation disappears on clicking the first row), but the expansion row does not appear.

Does anyone see the problem? Thanks in advance.

Here's a StackBlitz of what I have. I've put the working example from the linked SO answer in side by side with my broken example

./tweets-table/tweets-table.component.ts:

import { Component, OnInit } from '@angular/core';

import { animate, state, style, transition, trigger } from '@angular/animations';

import { Tweet } from '../tweet';
import { TweetService } from '../tweet.service';
import { TweetsDataSource } from '../tweets.datasource';
import { data } from '../mock-tweets';

@Component({
selector: 'app-tweets-table',
templateUrl: './tweets-table.component.html',
styleUrls: ['./tweets-table.component.css'],
animations: [
    trigger('detailExpand', [
    state('collapsed', style({ height: '0px', minHeight: '0', visibility: 'hidden' })),
    state('expanded', style({ height: '*', visibility: 'visible' })),
    transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
    ]),
],
})
export class TweetsTableComponent implements OnInit {
// Data
displayedColumns = [
    'createdTime', 'tweetText', 'favoriteCount'
];
tweets: Tweet[];
expandedTweet: any;
dataSource: TweetsDataSource|null;

constructor(private tweetService: TweetService) {
}

ngOnInit() {
    this.getTweets();
}

getTweets(): void {
    // this.tweets = this.tweetService.getTweets(this.pageIndex, this.pageSize);
    this.tweets = data;
    this.dataSource = new TweetsDataSource(this.tweets);
}

isExpansionDetailRow = (i: number, row: Object) => {
    row.hasOwnProperty('detailRow');
}

}

./tweets-table/tweets-table.component.html:

<div class="example-container mat-elevation-z8">
    <mat-table #table [dataSource]="dataSource">

    <!--- Note that these columns can be defined in any order.
            The actual rendered columns are set as a property on the row definition" -->

    <!-- Time Column -->
    <ng-container matColumnDef="createdTime">
        <mat-header-cell *matHeaderCellDef> Tweet Time </mat-header-cell>
        <mat-cell *matCellDef="let tweet"> {{tweet.created_time}} </mat-cell>
    </ng-container>

    <!-- Text Column -->
    <ng-container matColumnDef="tweetText">
        <mat-header-cell *matHeaderCellDef> So Texty </mat-header-cell>
        <mat-cell *matCellDef="let tweet"> {{tweet.text}} </mat-cell>
    </ng-container>

    <!-- Favs Column -->
    <ng-container matColumnDef="favoriteCount">
        <mat-header-cell *matHeaderCellDef> Flava Favs </mat-header-cell>
        <mat-cell *matCellDef="let tweet"> {{tweet.favorite_count}} </mat-cell>
    </ng-container>

    <!-- Expanded Content Column - The detail row is made up of this one column -->
    <ng-container matColumnDef="expandedDetail">
        <mat-cell *matCellDef="let detail"> 
        Walk before you run. Here's more text: {{detail.tweet.text}}
        </mat-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns;"
            matRipple 
            class="element-row" 
            [class.expanded]="expandedTweet == row"
            (click)="expandedTweet = row"></mat-row>
    <mat-row *matRowDef="let row; columns: ['expandedDetail']; when: isExpansionDetailRow"
            [@detailExpand]="row.element == expandedTweet ? 'expanded' : 'collapsed'"
            style="overflow: hidden"> 
    </mat-row>
    </mat-table>
</div>

I think my DataSource object is okay. However, I'm having a hard time getting a full understanding of MatDataSource, so I'll include that, too.

./tweets.datasource.ts:

import { Component, OnInit } from '@angular/core';
import { DataSource } from '@angular/cdk/collections';
import { Observable, of } from 'rxjs';

import { Tweet } from './tweet';
import { TweetService } from './tweet.service';


export class TweetsDataSource extends DataSource<Tweet> {
    constructor(private tweets: Tweet[]) {
        super();
    }

    connect(): Observable<Tweet[]> {
        const rows = [];
        this.tweets.forEach(element => rows.push(element, { detailRow: true, element }));
        console.log('dataset rows:')
        console.log(rows);
        return of(this.tweets);
    }

    disconnect() { }
}

回答1:


tweets.datasource.ts

In the connect method you are returning the wrong stuff. It should return rows instead of this.tweets.

connect(): Observable<Tweet[]> {
    const rows = [];
    this.tweets.forEach(tweet => rows.push(tweet, { detailRow: true, tweet }));
    console.log('dataset rows:')
    console.log(rows);
    return of(rows);
}

tweets-table.component.ts

This also has a error the method isExpansionDetailRow should return a boolean value true or false (Not do nothing). So add the return. The original code does not need the return because it just uses one line without the brackets.

If an arrow function is simply returning a single line of code, you can omit the statement brackets and the return keyword. This tells the arrow function to return the statement. Reference => https://codeburst.io/javascript-understand-arrow-function-syntax-ab4081bba85b

  isExpansionDetailRow = (i: number, row: Object) => {
    return row.hasOwnProperty('detailRow');
  }

If you are interested in another way of doing this you can refer to this issue.

MatTable Expand Collapse Icon issue on pagination and sort



来源:https://stackoverflow.com/questions/54442038/angular-material-table-expandable-table-row-not-expanding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!