Remzi Ibrahim Zayid Remzi Ibrahim Zayid - 6 months ago 19
Ajax Question

Having trouble retrieving custom attribute from HTML Option. Getting back [object Object] instead

I've been struggling with this one all day. I'm making an ajax call to a hard coded JSON file and attempting to store some of the contents into option tags using custom attributes. When I try to retrieve the data that I'm storing in the custom attribute, I keep getting [object Object]. If I try to JSON.stringify() that, I just get "[object Object]" (same as before, except wrapped in double quotes).

Some advice would be very helpful.

This is my currently empty select tag in HTML:

<select id="attackList"></select>


Actual JSON file:

{"attacks":[
{
"attackName":"Jab (1)",
"attackData":{"hitFrame":"9", "faf":"26", "damage":"1.5"}
},

{
"attackName":"Jab (3)",
"attackData":{"hitFrame":"11", "faf":"34", "damage":"2.7"}
},

{
"attackName":"Dash Attack (Early)",
"attackData":{"hitFrame":"15", "faf":"47", "damage":"10"}
},

{
"attackName":"Dash Attack (Late)",
"attackData":{"hitFrame":"21", "faf":"47", "damage":"8"}
},

{
"attackName":"Forward Tilt (1)",
"attackData":{"hitFrame":"12", "faf":"32", "damage":"3.5"}
},

{
"attackName":"Forward Tilt (3)",
"attackData":{"hitFrame":"14", "faf":"43", "damage":"8.5"}
},

{
"attackName":"Up Tilt(1, Early)",
"attackData":{"hitFrame":"7", "faf":"27", "damage":"5"}
},

{
"attackName":"Up Tilt (1, Late)",
"attackData":{"hitFrame":"9", "faf":"27", "damage":"2"}
},

{
"attackName":"Up Tilt (2)",
"attackData":{"hitFrame":"11", "faf":"27", "damage":"6"}
},

{
"attackName":"Down Tilt (Weak)",
"attackData":{"hitFrame":"7", "faf":"26", "damage":"6"}
},

{
"attackName":"Down Tilt (Strong)",
"attackData":{"hitFrame":"7", "faf":"26", "damage":"7"}
},

{
"attackName":"Forward Smash (Weak)",
"attackData":{"hitFrame":"19", "faf":"68", "damage":"14"}
},

{
"attackName":"Forward Smash (Strong)",
"attackData":{"hitFrame":"19", "faf":"68", "damage":"16"}
},

{
"attackName":"Up Smash (Early)",
"attackData":{"hitFrame":"18", "faf":"65", "damage":"17"}
},

{
"attackName":"Up Smash (Mid)",
"attackData":{"hitFrame":"20", "faf":"65", "damage":"16"}
},

{
"attackName":"Up Smash (Late)",
"attackData":{"hitFrame":"22", "faf":"65", "damage":"15"}
},

{
"attackName":"Up Smash (Late)",
"attackData":{"hitFrame":"22", "faf":"65", "damage":"15"}
},

{
"attackName":"Down Smash (1)",
"attackData":{"hitFrame":"20", "faf":"69", "damage":"5"}
},

{
"attackName":"Down Smash (2, Early)",
"attackData":{"hitFrame":"25", "faf":"69", "damage":"16"}
},

{
"attackName":"Down Smash (2, Late)",
"attackData":{"hitFrame":"26", "faf":"69", "damage":"15"}
}
]}


AJAX call that populates the select tag:

$.ajax({
url: attackerFileName,
dataType: 'json',
type: 'get',
cache:true,
success: function(data){
$(data.attacks).each(function(index,value){
console.log(value.attackData);
dropdownOptions.append($("<option></option>").attr("data-value", value.attackData).text(value.attackName));
});
}
});


And the JS code that attempts to retrieve the custom attribute from the currently selected option:

var selectedAttack = $("#attackList option:selected").data("value");
console.log(selectedAttack);


Anyone have any clue why I can't get the actual "attackData" contents from the JSON to come back? If I add code to log the attackData element from the JSON BEFORE its stored into the custom attribute, it comes back just fine. But after I retrieve it, [object Object] is all I get.

Thanks so much in advance to anyone who takes the time to look into this!

Answer

The html options can only take primitive values as a string representation. When you set an option using the attr function, the string representation of the value is taken. In case it is an object, you will get back [object Object] as you are actually storing this value.

However, you can use the $.data function to set the data as an object.

Setting the data value in the following way should do the trick

$('<option></option>').data('value', value.attackData);

or as shown in the code snippet below

'use strict';

var mock = [{
  name: 'Option 1',
  value: {
    identifier: 'option1',
    value: {
      hello: 'world'
    }
  }
}, {
  name: 'Option 2',
  value: {
    identifier: 'option2',
    value: {
      world: 'hello'
    }
  }
}, {
  name: 'Option 3',
  value: {
    identifier: 'option3',
    value: {
      sentence: 'hello world'
    }
  }
}];

$(function() {
  setTimeout(function(data) {
    // fake postback
    var targetElement = $('#dropdown');

    data.forEach(function(item) {
      var option = $('<option></option>').data('value', item.value).text( item.name );
      $(targetElement).append( option );
    });

  }.bind(null, mock));

  $('#dropdown').on('change', function() {
    var si = this.selectedIndex,
      option = this.options[si],
      name = option.text,
      value = $.data( option, 'value' );

    $('#output').html(name + '<br/>' + JSON.stringify(value));
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="dropdown">
</select>
<div id="output">
</div>

Comments