list.js
list.js copied to clipboard
reIndex() on filtered list only indexes visible items and not the original list
Use case:
- Existing list is pre-generated via server
- User updates an item via a modal window, then the item html is then replaced with the updated version (this is very common with Rails)
- Trigger list.reIndex() to take into account the new data.
Everything would work correctly if the list is not being searched. If the list is being searched, calling reIndex() on the searched list will only grab the visible ones and it stops working properly.
I'm on listjs 1.1.1
This seems to be a duplicate of #388. The first issue is closed with what seems to be a 'won't fix' status. Is it the case ?
This problem make it nearly impossible to use filter or search with a list that can be modified with ajax code.
A possible solution to this issue would be to modify reIndex to:
- preserve the value of
self.searchedandself.filtered - instead of reinitializing
self.itemsjust remove the visible items and keep the non visible ones
I'm not sure if there would be side effects regarding self.matchingItems as I don't fully understand the difference with self.visibleItems.
If it can help someone, for now my less than satisfacting workaround is to:
- Show all the hidden item
- Call reIndex
- Re-hide the items I showed before the reIndex
This is how I am handling updating list.js when I have an AJAX action button. I have stripped the code down and changed some things to be a better example but the idea is you should have the "element" that is either your "list item" or a child of one. From there you can do a find on the "list" items to get the List's item.obj and update the values with the new ones.
<a href="#" onClick="check_city(this)">Check Off</a>
function check_city(item) {
var pItem = item.parentElement; // Get's the parent container element
var list_item = list.items.find(function(lItem) {
return lItem.elm === pItem;
});
if ( list_item ) {
var values = {
name: pItem.querySelector('.name').innerText,
city: pItem.querySelector('.city').innerText,
checked: pItem.querySelector('.checked').innerText,
}
list_item.values(values); // Updates List Values
}
}
If you use ajax and want to reindex, you can do it to retrieve everything after the ajax call : yourList.filter(); //reinitialise list (add all items in dom) yourList.reIndex(); //reinitialise index with items in dom projectFilter(); //apply filter //projectFilter is th name of my function who initialize variables with filters checked and selected. This function embedded : userList.filter(function(item) { // (...) code here with res = true/false });
I've just submitted a pull request with an alternative approach to solving this problem: https://github.com/javve/list.js/pull/652
This adds a refresh() method which rescans all existing items (including hidden ones) from their corresponding HTML elements. This means that hidden items are not removed from the list. It also means that any new rows are not added, but I've also provided an addItem() method for doing this explicitly.