RogerHN RogerHN - 2 months ago 14
Javascript Question

Error in function for sortable list using local storage

I am using this function with framework7 sortable lists to save the position of the order of the list, I can save them to local storage, but I can't read them, I got this error:

Uncaught TypeError: Cannot read property 'id' of undefined

And its reffering to this line:

if (ls[j] === itemsArr[i].dataset.id) {


Here's my full function:

var list = document.getElementById('my-id');
var items = list.children;
var itemsArr = [];
for (var i in items) {
itemsArr.push(items[i]);
}
// localStorage
var ls = JSON.parse(localStorage.getItem('data-user-sort') || '[]');

for (var j = 0; j < ls.length; j++) {
for (i = 0; i < itemsArr.length; ++i) {
if (ls[j] === itemsArr[i].dataset.id) {
list.appendChild(itemsArr[i]);
}
}
}


$('.list-block.sortable').on('sort', function () {
var newIdsOrder = [];
$(this).find('li').each(function(){
newIdsOrder.push($(this).attr('data-id'));
});

localStorage.setItem('data-user-sort', JSON.stringify(newIdsOrder));
});


and here my html:

<div class="list-block sortable">
<ul id="my-id">
<li data-id="1">
<a href="#" class="item-link item-content">
<div class="item-inner">
<div class="item-title">Item 1</div>
</div>
</a>
<div class="sortable-handler"></div>
</li>
<li data-id="2">
<a href="#" class="item-link item-content">
<div class="item-inner">
<div class="item-title">Item 2</div>
</div>
</a>
<div class="sortable-handler"></div>
</li>
<li data-id="3">
<a href="#" class="item-link item-content">
<div class="item-inner">
<div class="item-title">Item 3</div>
</div>
</a>
<div class="sortable-handler"></div>
</li>
</ul>
</div>


Any help?

Answer

The problem is that your itemsArr variable does not only contains "li" objects, so when you iterate over it, you end up trying to access to the "dataset" property on objects where it doesn't exist.

If you debug your javascript, you will see that you have 3 "li" classes, the list's length and 2 functions (item() and namedItem()) and because of that, you get that error after the third iteration.

As someone else already said, you first need to verify if the property exists, but the code that he provided you will fail because he's also checking the property id of dataset, which is an undefined value. This code should work for you:

for (var j = 0; j < ls.length; j++) {
  for (i = 0; i < itemsArr.length; ++i) {
    if(itemsArr[i].dataset !== undefined){
      if (ls[j] === itemsArr[i].dataset.id) {
         list.appendChild(itemsArr[i]);
      }
    }
  }    
}

You can also check this jsfiddle with that validation https://jsfiddle.net/7bv849wc/1/

Edited because I forgot to add the index on itemsArr*