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
Implement array-selector. Fixes #4154 #4230
Conversation
* @param {*} item Item from `items` array to select | ||
*/ | ||
select(item) { | ||
let idx = this.items.indexOf(item); |
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 used to be O(1) in v1, but now it's O(n), I just hit this problem in iron-list...
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 removal of Collection
ultimately drives this change since collection.getKey(item)
was O(1). One option would be to introduce a selectIndex(idx)
and deselectIndex(idx)
API which would avoid the item->index lookup when the index is known apriori (e.g. selection following tap on a dom-repeat
'ed item).
When you say ' I just hit this problem in iron-list...', what do you mean? You hit a real-world performance problem due to this particular implementation? Or a similar O(n) problem elsewhere?
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.
yea. I was mostly thinking about multi-selection using the shift
key or any other pattern that triggers this path to select an item. In iron-list, I'll also need to call this.items.indexOf(item)
to preserve item.selected
in the model.
selectIndex(idx)
👌
|
||
_updateSelection(multi, itemsInfo) { | ||
if (itemsInfo.path == 'items') { | ||
let newItems = itemsInfo.base; |
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 observer might run even when newsItems
is undefined
causing a:
Uncaught TypeError: Cannot read property 'length' of undefined
from calculateSplices (array-splice.html:251)
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.
Thanks! Fixed.
let splices = Polymer.ArraySplice.calculateSplices(newItems, lastItems); | ||
this._applySplices(splices, lastItems); | ||
} else { | ||
this.clearSelection(); |
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.
clearSelection
also initializes this.selected
but not always. If lastItems
is an array and I set multi=true
after, then selected
is undefined
.
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 didn't totally grok how you could have a lastItems
and selected
be undefined
, but I think I see a case where you could switch multi
and not have selected
reflect a clear selection (i.e., in single selection it should be null
and in multi selection it should be []
), so I updated so that clearSelection
is always run when multi
changes.
0872998
to
109541c
Compare
this.linkPaths('selected.' + sidx, 'items.' + (idx + added - removed)); | ||
let selected = new IntegerSet(); | ||
let sidx = 0; | ||
this._selectedSet.forEach(idx => { |
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.
Apparently, the new set is created here because adding to a set while inside forEach
is not supported. If that's the confirmed, let's add a comment.
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.
Can't seem to confirm that root issue so this needs explanation.
@@ -158,58 +187,48 @@ | |||
} | |||
|
|||
_applySplices(splices) { | |||
let toRemove = []; |
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.
Need a comment here to explain a fundamental limitation of this approach: if an array is re-ordered the same element may be removed and re-added. In this case, it may not be detected as still being in the selection and therefore the selection will not be maintained in that case.
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
b719995
to
b154e2d
Compare
Implements
<array-selector>
for 2.x.Polymer.Element
class syntaxPolymer.Collection
; instead uses splice information to adjust linked indices between theitems
&selected
arraysPolymer.ArraySplice
(Levenshtein minimum edit distance algorithm); this makesarray-selector
compatible with the proposed changes to object dirty checking in 2.0. However, this is a small break in API behavior (previously setting to a new array would clear selection; it no longer necessarily does).selected
array/item (in 1.x you had to manually deselect first, which seemed onerous)Reference Issue
Fixes #4154