Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tabs): add ability to lazy load tab content #8921

Merged
merged 8 commits into from
Feb 8, 2018

Conversation

amcdnl
Copy link
Contributor

@amcdnl amcdnl commented Dec 10, 2017

This PR adds the ability to lazy load tabs, it is a new cut of #6832 on latest code.

@amcdnl amcdnl self-assigned this Dec 10, 2017
@amcdnl amcdnl requested a review from andrewseguin as a code owner December 10, 2017 19:52
@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Dec 10, 2017
@@ -24,6 +24,7 @@ import {
import {CanDisable, mixinDisabled} from '@angular/material/core';
import {Subject} from 'rxjs/Subject';
import {MatTabLabel} from './tab-label';
import { MdTabContent } from './tab-content';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No spaces between brackets?

Copy link
Member

@josephperrott josephperrott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@josephperrott josephperrott added pr: lgtm action: merge The PR is ready for merge by the caretaker target: minor This PR is targeted for the next minor release labels Dec 11, 2017
@jelbourn jelbourn removed the action: merge The PR is ready for merge by the caretaker label Dec 12, 2017
@jelbourn
Copy link
Member

I'd like @andrewseguin to take a look at this as well

count = 0;
ngOnInit() {
this.count++;
console.log('Counting...', this.count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide some comments about why we are console.loging and what the use of this Counter is?


<h1>Lazy Loaded Tabs</h1>
<mat-tab-group>
<mat-tab label="First">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs consistent two-space indentation

@@ -80,6 +80,30 @@ The `tab-nav-bar` is not tied to any particular router; it works with normal `<a
the `active` property to determine which tab is currently active. The corresponding
`<router-outlet>` can be placed anywhere in the view.

## Lazy Loading
By default, the tab contents are eagerly loaded. Eagerly loaded tabs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention here about how lazy-loading resolves issues with components that expect to be in the DOM while they setup? e.g. expansion panels and nested ink bars.

I suspect we'll want a place to point people to as we continue to get issues about this

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preferably yes. I'm waiting on a fix to #5269, to render expansion panels within tabs....as are others.

I'll probably use lazy loading in combination with a the Progress Spinner component since I render many expansion panels within a tab (see EDIT view on JSONSchema.Net).

Eagerly awaiting this feature :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrewseguin - Added, let me know what u think?


import {Directive, TemplateRef} from '@angular/core';

@Directive({selector: '[matTabContent]'})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs some doc describing the use and purpose of this directive

import {Directive, TemplateRef} from '@angular/core';

@Directive({selector: '[matTabContent]'})
export class MdTabContent {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MatTabContent =P

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some more MdTabContents lying around 😉

let fixture = TestBed.createComponent(TemplateTabs);
fixture.detectChanges();

let tabLabel = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to secondTabLabel to make it more obvious what we are doing here

@@ -45,8 +46,11 @@ export class MatTab extends _MatTabMixinBase implements OnInit, CanDisable, OnCh
/** Content for the tab label given by <ng-template mat-tab-label>. */
@ContentChild(MatTabLabel) templateLabel: MatTabLabel;

/** User provided template that we are going to use instead of implicitContent template */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Template provided in the tab content that will be used if present, used to enable lazy-loading"

declaring the body in a `ng-template` with the `matTabContent` attribute.

```html
<md-tab-group>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Md or Mat?

@amcdnl
Copy link
Contributor Author

amcdnl commented Dec 16, 2017

@andrewseguin - ready for round 2!

@amcdnl
Copy link
Contributor Author

amcdnl commented Jan 21, 2018

@josephperrott - ready for merge.

@jelbourn
Copy link
Member

@andrewseguin this PR still needs your approval

Copy link
Contributor

@andrewseguin andrewseguin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for your patience on the review. I'm excited to have this in as a solution for a lot of our issues open on tabs.

Add the merge ready label once the comments are addressed. Just minor nits that shouldn't affect the actual logic

export class Counter {
count = 0;
ngOnInit() {
this.count++;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not totally sure what the count represents, shouldn't this be 1 for any component regardless of how it is loaded?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, Its been so long I forgot what I was using it for too. I removed it.


If the tab contains several complex child components or the tab's contents
rely on DOM calculations during initialization, it is advised
to lazy load the tab's content. Tab contents can be lazy loaded by
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this statement should stand out a bit more, even just by making it a new paragraph:

"Tab contents can be lazy loaded by declaring the body in a ng-template with the matTabContent attribute."


<h1>Lazy Loaded Tabs</h1>
<mat-tab-group>
<mat-tab label="First">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be neat to see a third tab that doesn't use lazy-loading so we can see the difference somehow (e.g. the content of Counter component should have the time it was loaded?)

@aalbericio
Copy link

This PR is a must for our application 👍

Will it make it for next version?

@amcdnl
Copy link
Contributor Author

amcdnl commented Jan 26, 2018

@andrewseguin - resolved all comments.

})
export class Counter {
ngOnInit() {
console.log('Tab Loaded:');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smallest nit ever: remove the colon ;)

@andrewseguin andrewseguin added the action: merge The PR is ready for merge by the caretaker label Jan 26, 2018
@Component({
moduleId: module.id,
selector: 'counter',
template: `<span>{{count}}</span>`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

count variable is not defined

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amcdnl this is a presubmit error in Google, so if you can fix that it should unblock moving forward

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@mmalerba mmalerba merged commit 6feaf62 into angular:master Feb 8, 2018
tinayuangao pushed a commit that referenced this pull request Feb 9, 2018
* feat(tabs): add ability to lazy load tab content

* fix: lint

* chore: nit

* chore: pr feedback

* fix: presubmit error
@amcdnl amcdnl deleted the lazy-tabs branch February 10, 2018 15:14
@martinsafsten
Copy link

Just tried this out on the 6.0.0-beta-0 version. It seems to load the content as expected.

The problem I'm having is that the content is being recreated every time you navigate to the tab. I've seen this exact behavior before when using a ng-template in combination with a *ngIf to toggle it. Seems like a similar situation here.

I would want it to lazy load it when the tab is created, not when navigated to...

@aalbericio
Copy link

I'd prefer to set that behaviour externally: something like a "creationPolicy" param with values like:

  • CREATE_ALL
  • CREATE_CURRENT
  • RECYCLE
  • ...

Best.

@julianobrasil
Copy link
Contributor

julianobrasil commented Feb 14, 2018

@Marfyy and @aalbericio, the original issue (referring to #5269) was that to get animations to work inside a hidden tab some hacking was needed. IMO, this is fulfilled, as no hacking is necessary anymore.

Maybe starting another issue asking to improve the lazy load feature is the best you can do now. This issue (again, referring to #5269) is likely to be closed as soon as 6.0.0 is officially released.

@aalbericio
Copy link

Of course! That's more like a feature request. You're right! ;)

@martinsafsten
Copy link

agreed :)

@waterskier2007
Copy link

What version is this available in? Any 5.x.x versions or not until 6?

@julianobrasil
Copy link
Contributor

Not until 6.

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.