-
Notifications
You must be signed in to change notification settings - Fork 25
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: add load more pager to filters #3760
Conversation
Thanks for the PR! 🎉 We've deployed an automatic preview for this PR - you can see your changes here:
|
const dimensionKey = e.target.parentNode.id.slice(SET_DIMENSION_ID_PREFIX.length); | ||
|
||
/** @ignore */ | ||
this.dispatchEvent(new CustomEvent('d2l-filter-dimension-load-more', { |
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.
Would a consumer ever try to do this?
<d2l-filter-dimension-set @d2l-filter-dimension-load-more=${...}>...</d2l-filter-dimension-set>
Are we sure the <filter>
is the correct element to dispatch the event?
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.
Consumers would need to check for the key in the event. I replicated the behavior for the d2l-filter-dimension-empty-state-action
, since rendering happens on filter it is also responsible for dispatching events.
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 are we /** @ignore */
-ing the event?
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.
Yeah having the filter
dispatch all the events is a side-effect of our choice to have filter render everything, which we recently met about and decided not to change, even with the limitations. I think we could technically dispatch the event off the corresponding data-only dimension component, but like @GZolla mentioned the other dimension-specific events currently don't work this way. I'm also not sure if the analyzer for the Daylight site would understand where to put the event in that case?
|
||
return html`<d2l-filter-dimension-set key="${dimension.key}" text="${dimension.text}" ?pager-has-more="${loadedItems.length < items.length}"> | ||
${repeat(loadedItems, item => item.key, item => html` | ||
<d2l-filter-dimension-set-value key="${item.key}" text="${item.text}"></d2l-filter-dimension-set-value> |
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.
Looks like loading more items unselects everything, which I suspect is just be a demo problem. I think you'd need to handle tracking and setting the selected state like this demo does. Which I think is worth it, to give people a realistic example.
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.
The last commit modifies the demo to handle this
const dimensionKey = e.target.parentNode.id.slice(SET_DIMENSION_ID_PREFIX.length); | ||
|
||
/** @ignore */ | ||
this.dispatchEvent(new CustomEvent('d2l-filter-dimension-load-more', { |
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 are we /** @ignore */
-ing the event?
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.
So this is probably a @geurts question, but one thing this doesn't handle at all is selected items that haven't been loaded. If the filter is pre-populated with some selected things (like in Quick Eval where filters are re-applied when hitting the back button), and those items aren't included in the initial load, all the counts we show will be wrong because we expect to have all options.
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.
The demo now uses the same logic we use for search: we add all items but hide them and then show only those that are "loaded". This means the count will be correct even when some values are hidden by the search or the load more.
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.
Also, if a consumer is using load more they'll have to be using manual search, we don't have all the values to search for them. Should we enforce that somehow, like ignore the search
value set and pass manual
if has-more
is set? Maybe another @geurts question
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'm not sure what the best approach is here, but looking at other components we could just leave it as is. If manual search is not set the load more will work but the search would just filter the added items which sort of breaks its use. To me this is similar to failing to add keys to list items, we don't generate a key but just let the component break, meaning that the consumer is solely responsible for properly setting up the component.
Visual diff tests failed - pull request #3788 has been opened with the updated goldens. |
Co-authored-by: github-actions <[email protected]>
- Remove /** @ignore */ from load more event and add documentation - Fix demo resetting selection - Modify the complete callback to take the keys to be loaded
…re into gzolla/filter-load-more
* Wether the dimension has more values to load | ||
* @type {boolean} | ||
*/ | ||
pagerHasMore: { type: Boolean, attribute: 'pager-has-more', reflect: true }, |
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.
pagerHasMore: { type: Boolean, attribute: 'pager-has-more', reflect: true }, | |
hasMore: { type: Boolean, attribute: 'has-more', reflect: true }, |
I wonder if just has-more
would be better here, since a consumer doesn't really know we're using pager
under the hood
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 still like this being named has-more
to avoid revealing implementation details.
{ key: 'chemistry', selected:false, text: 'Chemistry' }, | ||
{ key: 'drama', selected:false, text: 'Drama' }, | ||
{ key: 'english', selected:false, text: 'English' }, | ||
{ key: 'how-t selected:false,o', text: 'How To Write a How To Article With a Flashy Title' }, |
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.
{ key: 'how-t selected:false,o', text: 'How To Write a How To Article With a Flashy Title' }, | |
{ key: 'how-to', selected:false, text: 'How To Write a How To Article With a Flashy Title' }, |
* Wether the dimension has more values to load | ||
* @type {boolean} | ||
*/ | ||
pagerHasMore: { type: Boolean, attribute: 'pager-has-more', reflect: true }, |
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 still like this being named has-more
to avoid revealing implementation details.
@@ -45,7 +50,7 @@ class FilterDimensionSet extends LitElement { | |||
* Whether to render the selected items at the top of the filter | |||
* @type {boolean} | |||
*/ | |||
selectedFirst: { type: Boolean, attribute: 'selected-first' }, | |||
selectedFirst: { type: Boolean, attribute: 'selected-first', reflect : true }, |
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.
Is the reflect
needed to work, or is it just to tell the consumer we changed the value on them?
willUpdate(changedProperties) { | ||
if (changedProperties.has('hasMore') && this.hasMore) { | ||
if (this.searchType !== 'manual') { | ||
console.warn('Paging requires search type set to manual.'); | ||
this.hasMore = false; | ||
} | ||
else this.selectedFirst = true; | ||
} | ||
} |
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.
Interested in some other opinions here. Currently, if you've set has-more
but not search-type="manual"
, we turn off has-more
and don't render the pager. We can't just turn on manual search for them, because they won't have events setup to handle it. Then, if they have correctly configured search, we override their setting of selected-first
because we also require that to be on (and we can force that on for them, there's nothing they need to do).
This fails pretty gracefully, but just wondering if we should actually be more destructive to make it obvious things are misconfiguring? Should we log a console error in one or both scenarios, and/or be less graceful and more obviously broken?
I'm good with this, but wanted to check since we've used a few different strategies across core
before
components/filter/filter.js
Outdated
if (dimension.selectedFirst) { | ||
this._updateDimensionShouldBubble(dimension); | ||
} |
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.
Are we now running this twice for the search scenario (once here, and then again above)?
If so, could we move it into _performDimensionSearch
? Seems like that hits all paths - automatic search, manual search, and search after load more?
this.dispatchEvent(new CustomEvent('d2l-filter-dimension-load-more', { | ||
detail: { | ||
key: dimensionKey, | ||
value: dimension.searchValue, |
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.
Maybe searchValue
to make it clear, or currentlyAppliedSearch
?
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.
My thought process was to have the same attribute names between this and the manual search event. Since we also decided to document those together, I think it makes it more intuitive to the consumer.
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.
Do you know why this visual diff is here? I wonder if merging main
in would remove this, doesn't seem related to your changes
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 realized we should probably add a visual-diff test that shows the load-more pager, and has a couple values selected-first but selected-first
isn't applied. But I'm fine with that being a follow-up PR!
@@ -31,6 +31,11 @@ class FilterDimensionSet extends LitElement { | |||
* @type {boolean} | |||
*/ | |||
loading: { type: Boolean }, | |||
/** | |||
* Wether the dimension has more values to load |
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.
* Wether the dimension has more values to load | |
* Whether the dimension has more values to load. Must be used with selected-first and search-type="manual" |
Could also be done as part of the documentation story if you're trying to get this merged before branching!
Also, just realized the focus is being lost after hitting "Load More". @dbatiste, is this something the list is supposed to handle automatically, or the consumer has to? |
I don't think focus should be lost. There were some previous changes that would disable the button while loading, and that did cause focus to be lost, but that was removed a long time ago. Focus should stay on the button while loading, and when the consumer calls |
🎉 This PR is included in version 2.134.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
@GZolla Is there a defect or something to track this? Just don't want to forget about it |
Adding load more pager to filters. Added the
pager-has-more
property tod2l-filter-dimension-set
that when set will render ad2l-pager-load-more
button (rendering done ind2l-filter
).The handling of pagination and adding/removing the property from the dimension is still the responsibility of the consumer (see the added demo as an example).
Rally: US153373