-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
feat(expansion-panel): allow for content to be rendered lazily #8243
Conversation
src/lib/expansion/expansion-panel.ts
Outdated
} | ||
}); | ||
|
||
// Remove the content once the panel is closed and the closing animation is done. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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
src/lib/expansion/expansion-panel.ts
Outdated
@@ -127,12 +147,31 @@ export class MatExpansionPanel extends _MatExpansionPanelMixinBase | |||
return this.expanded ? 'expanded' : 'collapsed'; | |||
} | |||
|
|||
ngAfterViewInit() { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9dd9c2c
to
ac73028
Compare
8d4354c
to
932c58e
Compare
Rebased and reworked the approach to take an |
if (this._lazyContent) { | ||
// Render the content as soon as the panel becomes open. | ||
this.opened.pipe( | ||
startWith(null!), |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
src/lib/expansion/expansion.md
Outdated
### 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. |
There was a problem hiding this comment.
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>
```
932c58e
to
5677639
Compare
Addressed the feedback @jelbourn. |
There was a problem hiding this 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>) {} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
f6ef924
to
1d2c440
Compare
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.
1d2c440
to
65a3a85
Compare
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
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.