0

I'm working on bootstrap-multiselect, I'm trying to add data attributes in the dataprovider method.

Current

var options = [
        {label: 'Option 1', title: 'Option 1', value: '1', selected: true},
        {label: 'Option 2', title: 'Option 2', value: '2'}];

In the code it maps these an <option> tag like so:

$tag = $('<option/>').attr({
                        value: option.value,
                        label: option.label || option.value,
                        title: option.title,
                        selected: !!option.selected,
                        disabled: !!option.disabled
                      });

Desired

var options =[
  {
    "label": "Item 1",
    "value": 1,
    "selected": false,
    "attributes": [
      {
        "some-attribute": 10001
      },
      {
        "another-attribute": "false"
      }
    ]
  }
]

So it will render on the HTML element as data-some-attribute="10001" data-another-attribute="false".

I started out adding this to the code (which I know won't work):

$tag = $('<option/>').attr({
                        value: option.value,
                        label: option.label || option.value,
                        title: option.title,
                        selected: !!option.selected,
                        disabled: !!option.disabled,
                        forEach(option.attributes, function(attribute){

                        })
                    });

The problem of course is you can't add a loop as an objects properties. Once this is working I can add a pull request to the repository. I did ask a question on the repo but decided to try and tackle it myself Issue #592 Any ideas?

ZeroBased_IX
  • 2,667
  • 2
  • 25
  • 46
  • Instead of adding another field `attributes`, why don't you just put them one after the other? (`label`, `value`, `selected`, `some-attribute`, `another-attribute`) – Lucian Aug 01 '15 at 12:10
  • How would I identify them? If I'm to add this as a pull request it needs to be dynamic and allow the user to add as many attributes as they want. It would be easy to add one attribute, but multiple user-defined data attributes makes it a tad tricky. – ZeroBased_IX Aug 01 '15 at 12:12
  • 2
    The iteration has to happen after the element was created, as in `$.each( option.attribute, function(att) { $tag.attr( Object.keys(att)[0], att[0] ) });` – adeneo Aug 01 '15 at 12:16

2 Answers2

1

I would suggest changing attributes from an array to an object, since attribute names should be unique. It also simplifies how you would get the data attributes on the element.

var attributes = {
  value: option.value,
  label: option.label || option.value,
  title: option.title,
  selected: !!option.selected,
  disabled: !!option.disabled
};

for (key in option.attributes) {
  attributes['data-' + key] = option.attributes[key];
}

$tag = $('<option/>').attr(attributes);

If you wanted to keep it as an array, you can do the following:

var attributes = {
  value: option.value,
  label: option.label || option.value,
  title: option.title,
  selected: !!option.selected,
  disabled: !!option.disabled
};

for (var i = 0; i < option.attributes.length; i++) {
  var key = Object.keys(option.attributes[i])[0],
      val = option.attributes[i][key];

  attributes['data-' + key] = val;
}

$tag = $('<option/>').attr(attributes);

Doing this, however, provides no benefit and introduces complexity. If each object can have multiple keys, the code will need to change further.

Zachary Kuhn
  • 1,152
  • 6
  • 13
  • Trying to test it, since Object.assign is ECMA6 and largely unsupported, is there another way to achieve the same results in a similar fashion? https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign – ZeroBased_IX Aug 01 '15 at 12:30
  • Yes, just made modifications so you will not need `Object.assign`. Good catch. – Zachary Kuhn Aug 01 '15 at 12:36
  • Works great, regarding your suggestion about using an object instead of an array. Doesn't this limit the number of data attributes I can add? – ZeroBased_IX Aug 01 '15 at 12:52
  • 1
    It limits the data attributes to being unique, but you can have a nearly unlimited number of keys in the object. – Zachary Kuhn Aug 01 '15 at 13:00
1

You need to create the element first then add the attributes to it.

So your code should be like this:

var options = [{
  "label": "Item 1",
  "value": 1,
  "selected": false,
  "attributes": [{
    "some-attribute": 10001
  }, {
    "another-attribute": "false"
  }]
}]

console.log(options.length);
$.each(options, function(option) {
  var $tag = $('<option/>').attr({
    value: options[option].value,
    label: options[option].label || options[option].value,
    title: options[option].title,
    selected: options[option].selected,
    disabled: options[option].disabled
  });
  console.dir(option);

  $.each(options[option].attributes, function(att) {
    $tag.attr("data" + Object.keys(att)[0], att[0])
  });
  $("#mySelect").append($tag);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<select id="mySelect">

</select>
cнŝdk
  • 31,391
  • 7
  • 56
  • 78