How to reset/refresh tab body data in Angular Material if user move from one tab to another tab?
Asked Answered
L

3

11

Here is my sample code

Main Controller

<mat-tab-group id="report">
<mat-tab label="Poll">
<div class="demo-tab-content">
  <app-poll></app-poll>
</div>

</mat-tab>
<mat-tab label="Survey">
<div class="demo-tab-content">
  <app-survey></app-survey>
</div>
</mat-tab>

In each tab, there is different controller named - Poll and Survey. Here I want to refresh\reset one tab data if the user moves from one to another.

Any simple way to achieve that?

Lyonnaise answered 3/4, 2018 at 12:7 Comment(3)
Possible duplicate of Angular 2 How to "watch" for tab changesFloatable
@Floatable I tried above code but it is not working for me. It directly navigating to brand new route which I don't want. Need to stay on the current tab but data should be refreshed after the tab changeLyonnaise
See my answer if it helpsFloatable
F
14

If you don't want to use @Input parameters, you can also use @ViewChild to get a reference to your child components and then call a method on these components to refresh the data

component.ts

  import {ViewChild} from '@angular/core';
  import { MatTabChangeEvent } from '@angular/material';
  //...
  @ViewChild(PollComponent) private pollComponent: PollComponent;
  @ViewChild(SurveyComponent) private surveyComponent: SurveyComponent;


  //...
  onTabChanged(event: MatTabChangeEvent) 
  {
    if(event.index == 0)
    {
        this.pollComponent.refresh();//Or whatever name the method is called
    }
    else
    {
        this.surveyComponent.refresh(); //Or whatever name the method is called
    }
  }

component.html

<mat-tab-group id="report" (selectedTabChange)="onTabChanged($event)">

</mat-tab>
Floatable answered 3/4, 2018 at 13:4 Comment(3)
I've tried setting it up like this but this.surveyComponent is not defined, so the refresh doens't get triggered... any idea why? Looks good on paper to me thoughBar
@Bar Maybe post a new question with a stackblitz exempleFloatable
my bad, my components weren't parent-child ;-) thanks for replying thoughBar
O
4

In angular material 8, there is an option for lazy loading the component in tabs when user selects it.

you can simply wrap your component to be lazy loaded in ng-template as shown in link below

https://material.angular.io/components/tabs/overview#lazy-loading

Overwrought answered 8/6, 2019 at 18:37 Comment(0)
R
1

You can read about component interaction types here.

You need something like this:

1. Children -> parent

In both of the components, have an need an emitter.

MainController:

  <app-poll (changed)=this.update($event)></app-poll>

  <app-survey (changed)=this.update($event)></app-survey>

In the components, have an event emitter defined:

@Output() changeEmitter = new EventEmitter<any>();

when you want to trigger the reset, write something like this:

changedEmitter.emit(<<you can insert objects here>>);

This will trigger the call in their parent's this.update().

in that method, you can define other logic to trigger a reset, but from parent-child, the easiest way is to bind a data object, which you can change:

2. Parent-> children

  <app-survey (changed)=this.update(newValue) [data]="surveyData"></app-survey>

in the main comp ts:

private surveyData: any;

update(newValue: any){
  surveyData =  <<something>>
}

in the survey comp:

@Input() private data: any;
Rattly answered 3/4, 2018 at 12:16 Comment(7)
Is there any other way than above one?Lyonnaise
the comment below reflects to that, although I do not think that that solution is clean-code. It feels wrong to call a different components functions directly, as it is supposed to be encapsulated iside the component and accessed via it's interface in my opinion.Rattly
Yes exactly. But I am new to angular hence I am not able to decide which one is better. Can you explain or any reference code for about comment? It would be grateful..!Lyonnaise
Angular uses an automatic change detection in the DOM. If somhing triggers it, it re-renders only part of the document - only the ones, Angular think it needs to update as it is a resource-heavy and costly operation. To narrow down the required re-rendering parts, you should stick to the official recommendations: from parent to child use direct binding, and from children to parent use event emitters. As the DOM is a tree representation, following the flow of that tree, you can achive quite fast updates. SourceRattly
did this answer help you?Rattly
Nope. Still not able to achieve that. I have tried what suggested by @Floatable approach for the temporary purpose.Lyonnaise
@Floatable as per documentation of an Angular Material I have used Tabs and navigation [material.angular.io/components/tabs/… which exactly do the same thing what Tab does with the router link parameter. I have to post an answer to my own question but due to less reputation not able to do that how do i submit that?Lyonnaise

© 2022 - 2024 — McMap. All rights reserved.