Removing a specific item from localStorage

I am adding some elements to localStorage using jQuery / JS and it is all fine, but when trying to remove a specific element in the array (if it is the same element) it becomes difficult.

In my console logs (for testing), [Object] seems to be cleared, but it doesn't update the key. Maybe my hierarchy is wrong ... any ideas?

//
function addToStorage(elem, name) {

    localData = localStorage.getItem(name + 'Storage');
    var typefaces;

    if (localData == 'null' || !localData) {
        typefaces = [];
    } else {
       typefaces = JSON.parse(localData);
    }

    typefaceID = elem.find('input').val();
    typefaceName = elem.find('input').attr('data-name');
    typefacePrice = elem.find('input').attr('data-price');
    typefaceQty = 1;

    $.each(typefaces, function(index, value) {
        if (value !== null) {
            if (value.id == typefaceID) {
                if (name == 'drf') {
                    //console.log(index);
                    //console.log(typefaces);
                    typefaces.splice(index, 1);
                    //console.log(typefaces);
                }
            }
        }
    });

    typefaces.push({
        'id': typefaceID,
        'name': typefaceName,
        'price': typefacePrice,
        'qty': typefaceQty
    });

    localStorage.setItem(name + 'Storage', JSON.stringify(typefaces));

}

//
$(document).on('click', 'summary.cart td.font', function(e) {
    e.preventDefault();
    addTo = $(this);
    addTo.each(function() {
        addToStorage(addTo, 'drf');
    });
});

      

This is an example of localData after adding it.

[  
   {  
      "id":"dr-raymond-desktop-40374",
      "name":"DR-Raymond",
      "format":"Desktop (OTF)",
      "price":"15.00",
      "qty":1
   },
   {  
      "id":"dr-raymond-webfont-39949",
      "name":"DR-Raymond",
      "format":"Webfont (WOFF)",
      "price":"15.00",
      "qty":1
   }
]

      

enter image description here

+3


source to share


5 answers


Never add / remove elements from an array while iterating over it with "foreach". Try this instead:

for (index = typefaces.length - 1; index >= 0; index--){
    value = typefaces[index];
    if (value !== null) {
        if (value.id == typefaceID) {
            if (name == 'drf') {
                typefaces.splice(index, 1);
            }
        }
    }
});

      

Another way to do it more elegantly is to use an ES6 () filter:



typefaces = typefaces.filter(value => !(value && value.id == typefaceID && name == "drf"));

      

Also, you are comparing localData

to a literal string 'null'

, which is pointless. In this case, your second condition if (!localData)

will handle it correctly.

+4


source


The problem is with your splicing method. Note that according to MDN, splice

modifies the array in-place and returns a new array containing the removed elements. So when you use a loop and try to remove some elements, the splice will cause the elements to shift. This is because the array is iteratively iterated over, as you splicate the array changes in place, so the elements are "shifted" and you end up skipping some iteration. Looping back fixes this because you are not looping in the direction you are splicing.

Solution 1

Roll back when spliced.

for(var i = typefaces.length; i--;)
{
            if (typefaces[i] !== null) 
            {

                if (typefaces[i] == typefaceID) 
                {
                        typefaces.splice(i, 1);
                }
            }
 }

      

The working container link is here .



Solution 2

It usually generates a new array faster instead of modifying an existing one. So your code will look like

ty = [];
   $.each(typefaces, function(index, value) {
        if (value !== null) {

            if (value.id != typefaceID) {
                    ty.push(value);
            }
        }
    });
  typefaces = ty;

      

Working buffer link here . After that there is no problem getting and setting up your local storage.

0


source


You have an additional error in your code, you write

if (value !== null) {
    if (value.id == typefaceID) {
        // name will always have the value drf 
        // since you pass it in your function
        // when you call it addToStorage(addTo, 'drf');
        if (name == 'drf') {
            typefaces.splice(index, 1);
        }
    }
}

      

when should it be

if (value !== null) {
    if (value.id == typefaceID) {
        // here the comparison should be between value.name and name
        if (value.name == name) {
            typefaces.splice(index, 1);
        }
    }
}

      

which can also be written

if (value !== null) {
    if (value.id == typefaceID && value.name == name) {
            typefaces.splice(index, 1);
    }
}

      

0


source


You are mutating the array by splicing it. The only localstorage elements that are rewritten are those that remain in the array.

Thus, remove the item from storage when splicing an object from an array.

$.each(typefaces, function(index, value) {
        if (value !== null) {
            if (value.id == typefaceID) {
                if (name == 'drf') {
                    //console.log(index);
                    //console.log(typefaces);
                    var removedTypeFace = typefaces.splice(index, 1);
                    //console.log(typefaces);

                    if(removedTypeFace) {
                        localStorage.removeItem(removedTypeFace.name + 'Storage');
                    }
                }
            }
        }
    });

      

-1


source


OK. You're going to kick yourself. The first time you run it from localStorage, the method getItem

returns a value null

, but you are trying to compare it with the string ( 'null'

, in quotes). Fail. I changed localData == 'null'

to localData == null

.

The second part of the expression tries to see that the value returned from getItem

is indeed defined, which is good. I changed this to be more explicit with help typeof

.

Explicit variable declarations also help.

function addToStorage(elem, name) {

    var localData = localStorage.getItem(name + 'Storage');
    var typefaces;

    if (localData == null || typeof(localData) == 'undefined') {
        typefaces = [];
    } else {
       typefaces = JSON.parse(localData);
    }

    var typefaceID = elem.find('input').val();
    var typefaceName = elem.find('input').attr('data-name');
    var typefacePrice = elem.find('input').attr('data-price');
    var typefaceQty = 1;

    $.each(typefaces, function(index, value) {
        if (value !== null) {
            if (value.id == typefaceID) {
                if (name == 'drf') {
                    //console.log(index);
                    //console.log(typefaces);
                    typefaces.splice(index, 1);
                    //console.log(typefaces);
                }
            }
        }
    });

    typefaces.push({
        'id': typefaceID,
        'name': typefaceName,
        'price': typefacePrice,
        'qty': typefaceQty
    });

    localStorage.setItem(name + 'Storage', JSON.stringify(typefaces));

}

//
jQuery(document).on('click', 'summary.cart td.font', function(e) {
    e.preventDefault();
    addTo = $(this);
    addTo.each(function() {
        addToStorage(addTo, 'drf');
    });
});
      

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<summary class='cart'><table><tr>
<td class='font' >Click Here for Item 1
<input data-name='abc' data-price='2.00' value="Item 1" /></td></tr>
<tr>
<td class='font' >Click Here for Item 2
<input data-name='def' data-price='4.00' value="Item 2" /></td></tr></table>
</summary>
      

Run code


-1


source







All Articles