Components: [Proposal] Tab content hidden option

Created on 21 Jun 2016  路  25Comments  路  Source: angular/components

Bug, feature request, or proposal:

Proposal

What is the expected behavior?

Tab content hiding instead of ngIf removing them from DOM

What is the current behavior?

Temporarily Removed from DOM and inserted again once ngIf is active

What is the use-case or motivation for changing an existing behavior?

Switching between tabs seems to be a lot faster for me after adopting the content hiding instead of ngIf, along with that I'm creating a socket connection within each content which is being reset every time I load a new tab.

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

All

Is there anything else we should know?

If allowed I'd like to post a pull request which would adapt both methods of doing this leaving the ngIf as default and only using hidden if a certain flag is used.

feature perf

Most helpful comment

I can see one other major bonus of hiding instead of removing the element from the dom, it's when the content of the tab is editable and unsaved. When switching tabs the changes are lost.
But once again both options should be supported as they both have their own use cases.

All 25 comments

Personnaly I prefer ngIf because I need content to reload when changing tabs.
Suppose I have two tabs
Tab1: managing roles and functionalities
Tab2: Managing user roles

If I add a new role in tab1 I need it to be shown on tab2 after switching tabs.

And I believe tab group is using portal host (no ngIf)

@robertmesserle we should look into the performance implications of this

Hi,

I think both case are very useful and depends on usage. It would be great to be able to choose which mode to use. Another great feature could be to load content only when the tab was selected once and then keep the content even when changing tabs.

Thanks.

@jelbourn For me the performance is amazing, switching between all of the tabs is a lot faster since I don麓t have to keep reconnecting.

@zigzag95 I know it's *ngIf as I've analysed the source code:
L23

What I did to make it work was quite simple, since [hidden] can't be used in a template, I had to surround it with a div and place the directive there.

Let me know if you want me to post a PR so you can test the performance.

@jelbourn @RicardoVaranda I think I agree that we should support both options. When dealing with a small number of tabs, hiding the inactive tabs will typically be faster; however, when dealing with a large number of tabs, this can cause performance issues.

The ideal solution would be something like what we _tried_ in Material 1 with disconnectScope, but I'm not sure if there's a good bug-free way to do that.

I can see one other major bonus of hiding instead of removing the element from the dom, it's when the content of the tab is editable and unsaved. When switching tabs the changes are lost.
But once again both options should be supported as they both have their own use cases.

Yes i agree that we should have both options, as @no-more mentioned, i have similar use case where i group the grid , now after switching tabs the grouping/filtering doesnt stay. The data bound to grid in different tabs are not the same , so putting the datamodel outside wont work in this case . @RicardoVaranda can you provide your solution if possible. Thanks

I will create a pull request with the solution for this in the morning.

Thanks @RicardoVaranda

Agree, but please make this an option as we are currently using the original feature whereby ngIf removes it from dom, this matches our user requirements !!! Please do not remove this feature :-)

@RicardoVaranda Did you make that pull request for [hidden] md-tabs? I couldn't find it. I'd really appreciate a look.

@FoodBuster You can use this temporary fix, I'll try and make time after work to release the full version with support for both:

https://github.com/RicardoVaranda/material2/blob/master/src/lib/tabs/tab-group.html#L23

@RicardoVaranda Much appreciated!

Sorry for the delay, I've created a PR for this:

https://github.com/angular/material2/pull/1472

This will allow us to use the tabs just like before but by passing hideTabs input of true it will hide the tab contents instead of removing and adding them to the DOM, there are some setbacks to this and it should be used with moderation, i.e you shouldn't hide the contents if you have a large number of tabs e.g 10+

Example below:

<md-tab-group [hideTabs]="true" class="demo-tab-group">
  <md-tab *ngFor="let tab of tabs; let i = index" [disabled]="i == 1">
    <template md-tab-label>{{tab.label}}</template>
    <template md-tab-content>
      {{tab.content}}
      <br>
      <br>
      <br>
      <md-input placeholder="Tab Label" [(ngModel)]="tab.label"></md-input>
    </template>
  </md-tab>
</md-tab-group>

+1 for allowing an option to hide without DOM teardown.

The other reason, I ran into is that, placing a (secondary) <router-outlet> into the tab content, means its content currently is not being re-populated after switching back and forth between tabs (while there is no route change). See tab-related issues #1445 and #524.

This item seems all the more important now.

As far as the "Tab + Router" issue #524 goes, it has just been closed with a solution that does not seem to address the use case I initially opened as issue #1445 (I.e. using a secondary router outlet as _one_ of the tabs in a tab-group.)

Tabs no longer use ngIf but attach/detach the content using a portalHost. Changes made to the content are preserved when switching tabs. I am not seeing any performance issues using this method.

@andrewseguin
I'm now using