3

i am trying to use jQuery.data() and save an Object to my HTML-Elements. Everytime i add an list-Element to my unordered List it only saves the last object to the specific li-Element. Every other li-Elements saved data gets thrown away!

I've built a little Example. JSBin-Example

On the left, i create a List with an Object saved to it. On the right i am trying to show the data related to the Object.

Why does it only show the Object related to the last HTML-Element?

Working example:
JSBin-Example

B. Kemmer
  • 1,517
  • 1
  • 14
  • 32
  • 2
    This code for starters could do with a massive refactor. Have a look into .attr() to add id's to elements and also have a look at .append() to get data inside the element. The code is really hard to read on your example. – The Angry Saxon Apr 30 '15 at 07:39
  • Also, you shouldn't use `for...in` loops with arrays like you've done here: `var item in testObject`. [Use a proper for loop instead.](http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea) – Andy Apr 30 '15 at 07:43
  • Why is it hard to read? It is a small and simple Example. I am adding data with $("#"+id).data(testObject[item]); Each time i add a new item the list gets updated. The data gets saved after i add it to the DOM. How can i make it more readable? – B. Kemmer Apr 30 '15 at 07:43
  • http://jsbin.com/ralizazahe/1/ have a quick look at the updateList() function now. Much easier to read and is starting to work. In terms of the data() function, I'm pretty sure you can't attach an object to it. You'll have to set individually. Although I could be wrong, just never used it that way. – The Angry Saxon Apr 30 '15 at 07:56
  • You should look into appending just the new li to the html though rather than clearing and re-entering all the data each time. This is a massive amount of work in comparison to what could happen. – The Angry Saxon Apr 30 '15 at 07:58
  • 1
    http://jsbin.com/ralizazahe/1/edit?js,console,output Have a quick look at that and question anything you don't understand. It's not about belittling your code but helping you understand how to better it. Hope it helps a little. Couldn't spend to much time on it but if you look in the console it's passing the correct values to your saved list but not actually populating. – The Angry Saxon Apr 30 '15 at 08:35

3 Answers3

2

That's because you are modifying innerHTML property of the wrapper element. What happens is in each iteration the elements are regenerated, the current elements are removed and the new elements don't have any stored data. Using innerHTML property is the worst way of modifying element contents. You just need to create a li element and append it to the wrapper element:

var random = 0;
// var testObject = [];

function addNewItem(){
  random += 1;
  var id = "testId" + random;
  var text = "This is my " + random + ". text";
  var data = {id: id, text: text};
  // testObject.push(data);
  // You can pass an object as the second argument 
  // to jQuery constructor and it calls the 
  // corresponding methods as setter
  $('<li></li>', {
      text: text + JSON.stringify(data),
      id: id,
      data: data
  }).appendTo('#listId'); 
}
// bind and trigger click event              
$("#add").on('click', addNewItem).click();
Ram
  • 143,282
  • 16
  • 168
  • 197
0

I changed

  for(var i = 0; i < testObject.length; i++){
        var listItem = "";
        var id = testObject[i].id;
        listItem += liStart + id + liStart2;
        listItem += testObject[i].text;
        listItem += liEnd;
        unorderedList.innerHTML += listItem;
        $("#"+id).data(testObject[i]);
      }

to this in your updatelist function

  //for(var i = 0; i < testObject.length; i++){
            var id = testObject[testObject.length-1].id;
            listItems += liStart + id+"savedData" + liStart2;
            listItems += JSON.stringify($("#"+id).data());
            listItems += liEnd;
          //}
          savedData.innerHTML += listItems;

and it fixed the issue

Fester
  • 863
  • 1
  • 12
  • 33
0

To help you understand my comment on the question I thought it best I'd give an example of what I meant.

I didn't have enough time to fully go through the solution but wanted to give an example of what I'd call more readable code.

I've added all variables at the top of the function. This will allow you to read and find items much quicker if you needed to alter them.

I've also merged a lot of the string values that you had into an object, namely the li element.

I've never used $.data() as an object before so wasn't really aware how I could use it to set the values in the updateSavedData() $('li'), although the console.log() does show the correct key / values.

  $(document).ready(function(){
    var uID = 0;
    var testObject = [];
    var unorderedList = $("#listId");
    var savedList = $("#savedData");
    var TOL = 0; //TestObjectLength
    var textTemplate = "This is my [0] text!";

    function addNewItem(){
      uID++;
      testObject.push({id: uID, text: textTemplate.replace("[0]", uID)});
      TOL = testObject.length-1;
      updateList();
    }

    function updateList(){
      var li = $('<li>', { id: testObject[TOL].id, data: testObject[TOL], text: testObject[TOL].text });
      li.appendTo(unorderedList);
      updateSavedData(li.data());
    }

    function updateSavedData(li){
      console.log(JSON.stringify(li));
      $('<li>', JSON.stringify(li)).appendTo(savedList);
    }

    addNewItem();
    $("#add").on('click', addNewItem);
  });

Working Example

http://jsbin.com/ralizazahe/1/edit?js,console,output

Anyone that wants to progress on that please do as I'd also like to see how this could be progressed more.


Update

Taken it a step more and refactored to this

  $(document).ready(function(){
    var $displayList = $("#listId");
    var $savedList = $("#savedData");

    var textTemplate = "This is my {0} text!";

    var uID = 0; //Unique ID
    var data = { id: null, text: null }; //Gives a reference

    function init(){
      uID++;
      data = { id: uID, text: textTemplate.replace("{0}", uID) };
    }

    function addNewItem(){
      init();
      $('<li>', data).appendTo($displayList);
      updateSavedData(data);
    }

    function updateSavedData(li){
      $('<li>', li).appendTo($savedList);
    }

    addNewItem();
    $("#add").on('click', addNewItem);
  });

http://jsbin.com/bajekagoli/1/edit?js,console,output

The Angry Saxon
  • 792
  • 2
  • 7
  • 24