angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.34k stars 6.74k forks source link

[Table] Emit event when after rendering rows #8068

Closed patricia-martinez-imatia closed 3 years ago

patricia-martinez-imatia commented 7 years ago

Bug, feature request, or proposal:

Resquest

What is the expected behavior?

Have an event that is emite when the table is rendered

What is the current behavior?

I have an example of a table with a lot of data and while not painting the table is blank and I would like to show a loading while it does not finish rendering the table. i only can control the call to service but not the rendered of the table. is there any way to know when I finish rendering the table?

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

"peerDependencies": { "@angular/flex-layout": "2.0.0-beta.9", "@angular/material": "2.0.0-beta.10", "@angular/cdk": "2.0.0-beta.10", "@angular/animations": "4.3.6", "@angular/common": "4.3.6", "@angular/compiler": "4.3.6", "@angular/compiler-cli": "4.3.6", "@angular/core": "4.3.6", "@angular/forms": "4.3.6", "@angular/http": "4.3.6", "@angular/platform-browser": "4.3.6", "@angular/platform-browser-dynamic": "4.3.6", "@angular/platform-server": "4.3.6", "@angular/router": "4.3.6", "@angular/upgrade": "4.3.6", "@angular/cli": "1.3.2", "@ngx-translate/core": "8.0.0", "@ngx-translate/http-loader": "1.0.2", "core-js": "^2.4.1", "rxjs": "^5.4.2", "zone.js": "^0.8.12", "reflect-metadata": "0.1.10" },

amcdnl commented 6 years ago

You could always just use the CDK Observer to get the render event. https://material.angular.io/cdk/observers/overview

Cammisuli commented 6 years ago

I'm interested in this as well. If a PR is needed, I'm more than happy to provide it.

kevin192291 commented 5 years ago

Any updates on this? If not, I would be happy to do some work on this

eduardoalcantara commented 5 years ago

I aways get an error when I need to get table element to do some math. It is always null when we need it, because I have to hide it and show to make it render after new data. renderRows() not working.

kevin192291 commented 5 years ago

Let me see if I can get this added and maybe they will let me do a PR, if not, i can send you my changes.

eduardoalcantara commented 5 years ago

The main problem is because Angular does not update the binded variables in the view in the correct moment, only after the entire code of the component is executed. Maybe if I do an detectChanges() before using renderRows()?

knoefel commented 5 years ago

Are there any news regarding this request?

ferakiii commented 4 years ago

Any ideas how to do this? I want to keep the scroll position of the table after navigating away then back. But I cannot find out when the table has been rendered, and so when I can set the scroll position. Any feedback on where this issue is at?

Hintalo commented 4 years ago

I had a similar problem with a material table where I wanted to set the scroll position after the data was updated. I use following workaround: I wait until the current Angular-Zone is getting stable (i.e. no more DOM manipulations, no more rendering). The "onStable" observable of the zone can be used for that purpose, see following code:

In your component:

    @ViewChild('tablecontainer', {read: ElementRef}) public tableContainerRef: ElementRef; // this is the scrollable container (ie. it has "overflow: auto" or "overflow: scroll")

    private desiredScrollPos: number; // this should be set to the position where you want to scroll to

    constructor(private renderer: Renderer2,  private zone: NgZone) {
        this.desiredScrollPos = -1; // this indicates that no programmatic scroll is required at the moment
        ...
    }

    public ngAfterViewInit(): void {
            this.setupOnStableObserver();
            ...
    }

    private setupOnStableObserver(): void {
        this.zone.onStable.pipe(debounceTime(300)).subscribe(() => {
            if (this.desiredScrollPos >= 0) {
                this.scrollTo(this.desiredScrollPos);
                this.desiredScrollPos = -1; // important, for indicating that no further programmatic scroll is required for the moment
            }
        });
    }

    private scrollTo(position: number): void {
        this.renderer.setProperty(this.tableContainerRef.nativeElement, 'scrollTop', position);
    }

After you update your table data, or set the initial data (which triggers rendering of the table in DOM), you should set the required scroll-position in this.desiredScrollPos (or -1 if no scroll is wanted). Then the code above takes care about waiting for the right moment for setting the scroll-position on the scrollable container.

fourgates commented 4 years ago

Any updates on this ticket? it would be very useful to know when a table has finished filtering.

vorong commented 4 years ago

tl;dr: I was able to get this to work by wrapping the call to give focus in a setTimeout(), but this feels very hacky, and it would still be good to have a proper event fire once MatTable has finished rendering.

I had a use case where I needed to give focus to a form field in a newly created row of my MatTable. So, I tried this:

const item: Item = this.createNewItem();
this.items.push(item);
this.dataSource = new MatTableDataSource<Item>(this.items);
document.querySelectorAll('.my-text-input-class')[0].focus();

But, when I did this, the new row was not available yet. Wrapping it in a setTimeout() with a delay of 0 seconds did the trick.

const item: Item = this.createNewItem();
this.items.push(item);
this.dataSource = new MatTableDataSource<Item>(this.items);
setTimeout(() => {
  document.querySelectorAll('.my-text-input-class')[0].focus();
}), 0);
djedovicdusan94 commented 3 years ago

Years passed, and still no update on this.

BazylPL commented 3 years ago

Shame. Event on render finish could be very useful

IgorKurkov commented 3 years ago

+1

brandonsmith86 commented 3 years ago

I'd find this useful as well.

pccosta-pdm commented 3 years ago

The palliative way that I used:

constructor(
  private apiService: ApiService,
  private ngZone: NgZone) {
}

anyFunction(): void {
  apiService.request().subscribe((resp) => {
    this.dataSource = new MatTableDataSource(resp.results);

    this.ngZone.onStable.pipe(first()).subscribe(() => {
      console.log('Finished rendering');
    });
  }
}
angular-automatic-lock-bot[bot] commented 3 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.