Skip to content

feat(expansion-panel): allow for content to be rendered lazily #8243

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

Merged

Conversation

crisbeto
Copy link
Member

@crisbeto crisbeto commented Nov 6, 2017

Currently the expansion panel renders all of its content on load which can be expensive, considering that all of it won't be visible. These changes allow for some of the content to be rendered lazily via the matExpansionPanelContent directive.

Fixes #8230.

@googlebot googlebot added the cla: yes PR author has agreed to Google's Contributor License Agreement label Nov 6, 2017
}
});

// Remove the content once the panel is closed and the closing animation is done.
Copy link
Member

Choose a reason for hiding this comment

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

What is the reasoning behind removing the content on closing? Since the issue we are looking to address is lazy loading, is there a reason to detach and reattach all the time?

Copy link
Member Author

Choose a reason for hiding this comment

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

I was a bit on the fence on this one as well, but it could help if you have some really massive panels with lots of elements. I'm open to not doing this though.

Copy link

@bardiel bardiel Nov 6, 2017

Choose a reason for hiding this comment

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

Could this be configured perhaps via an Input?
I'm developing (for learning purposes) an RSS feed reader. On desktop, each item is placed inside an expansion panel (for fancyness (?)); inspired by Google Inbox interface.

Removing the content inside the panel after been read, could be something I'd like to happen. Being that as more and more items are been loaded, more resources will be consumed. (O course I shall do something about this regardless of this specific feature).

However, also thinking about other Google products like GSuite admin console: where some settings are loaded asynchronously the first time, but then kept. (I don't know if they're actually removed from DOM, but I wouldn't remove them in such scenario).

Copy link
Member

Choose a reason for hiding this comment

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

I think it might be best at this point to not remove the content once it is placed and we can determine if it is something that we want to allow later, potentially as @bardiel mentioned via @Input

@@ -127,12 +147,31 @@ export class MatExpansionPanel extends _MatExpansionPanelMixinBase
return this.expanded ? 'expanded' : 'collapsed';
}

ngAfterViewInit() {
Copy link
Member

Choose a reason for hiding this comment

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

We have had a number of issues with content changed after checked for these situations, are we going to run into the same issue here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably not, those exceptions are usually if data bindings change. This is the same way we're doing it for tabs.

Copy link
Member

Choose a reason for hiding this comment

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

For tabs we actually are having to change it because of these issues #7266

We are creating a custom template portal and having the template portal itself be responsible for attachment because of issues with ChangeAfterContentChecked. I just want to be sure we don't accidentally create an issue further down the road.

<div class="mat-expansion-panel-body">
<ng-content></ng-content>
<ng-template><ng-content></ng-content></ng-template>
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't stop Angular from initializing stuff; we can make this change to stop stuff from making it into the DOM, but we'll ultimately need an alternate API where users provide an ng-template

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, I was under the impression that this was the reason we do it the way we do for the tabs. In that case I'll rework it to use a @ContentChild to find an ng-template and instantiate it.

Copy link
Contributor

Choose a reason for hiding this comment

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

@crisbeto - Look at what I did for #6832

@crisbeto crisbeto force-pushed the 8230/expansion-panel-lazy-load branch from 9dd9c2c to ac73028 Compare November 12, 2017 11:31
@crisbeto crisbeto changed the title perf(expansion-panel): render content lazily feat(expansion-panel): allow for content to be rendered lazily Nov 12, 2017
@crisbeto crisbeto force-pushed the 8230/expansion-panel-lazy-load branch 2 times, most recently from 8d4354c to 932c58e Compare November 12, 2017 11:33
@crisbeto
Copy link
Member Author

Rebased and reworked the approach to take an ng-template with matExpansionPanelContent instead. Can you take another look @jelbourn @josephperrott?

if (this._lazyContent) {
// Render the content as soon as the panel becomes open.
this.opened.pipe(
startWith(null!),
Copy link
Member

Choose a reason for hiding this comment

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

Why does this start with never?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because the opened stream won't emit if the panel is open by default. This ensures that we render any panels that are open on load.

### Lazy rendering

If you want some content not to be rendered until its expansion panel is opened, you can wrap it in
an `ng-template` using the `matExpansionPanelContent` directive.
Copy link
Member

Choose a reason for hiding this comment

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

How about

By default, the expansion panel content will be initialized even when the panel is closed.
To instead defer initialization until the panel is open, the content should be provided as
an `ng-template`:
```html
<mat-expansion-panel>
  <mat-expansion-panel-header>
    This is the expansion title
  </mat-expansion-panel-header>

  <ng-template matExpansionPanelContent>
    Some deferred content
  </ng-template>
</mat-expansion-panel>
```

@crisbeto crisbeto force-pushed the 8230/expansion-panel-lazy-load branch from 932c58e to 5677639 Compare November 14, 2017 18:05
@crisbeto
Copy link
Member Author

Addressed the feedback @jelbourn.

@jelbourn jelbourn added pr: lgtm action: merge The PR is ready for merge by the caretaker and removed pr: needs review labels Nov 14, 2017
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

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

LGTM

selector: 'ng-template[matExpansionPanelContent]'
})
export class MatExpansionPanelContent {
constructor(public _template: TemplateRef<any>) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a quick question: Don't you use _ for private variables only?

Copy link
Contributor

Choose a reason for hiding this comment

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

They also use it for "internal use only" properties

@crisbeto crisbeto force-pushed the 8230/expansion-panel-lazy-load branch 2 times, most recently from f6ef924 to 1d2c440 Compare November 20, 2017 20:31
Currently the expansion panel renders all of its content on load which can be expensive, considering that all of it won't be visible. These changes allow for some of the content to be rendered lazily via the `matExpansionPanelContent` directive.

Fixes angular#8230.
@crisbeto crisbeto force-pushed the 8230/expansion-panel-lazy-load branch from 1d2c440 to 65a3a85 Compare November 23, 2017 22:03
@crisbeto crisbeto added the target: minor This PR is targeted for the next minor release label Dec 6, 2017
@andrewseguin andrewseguin merged commit 60ba0a7 into angular:master Dec 13, 2017
@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 7, 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.

[mdExpansionPanel] - Feature request - Lazy load content
9 participants