2

JSfiddle: http://jsfiddle.net/cjVSj/

I have a simple select2 with the range of possible tags set by the tags option and the preloaded tags set by values in the input field in the html.

When the on change event fires on the select2, the removed item seems to lose its id, reporting instead its text value.

To see the problem, adding a tag (e.g. west) correctly reports the added.id, but removing the existing east tags reports id = east, not 1356.

Any insight into how to gain access to the id of a tag upon removal?

HTML:

<script>
   var tags = [{ "id": 1354, "text": "north", "restricted": false
   }, {"id": 1355, "text": "south", "restricted": false
   }, {"id": 1356, "text": "east", "restricted": false
   }, {"id": 1357, "text": "west", "restricted": false
   }]; 
</script>tags:
<input type="text" id="mytags" value="east" />

JS:

   $(document).ready(function () {
       $('#mytags').select2({
           placeholder: 'Search',
           allowClear: true,
           minimumInputLength: 2,
           multiple: true,
           tags: tags,
           tokenSeparators: [','],
       });


       $('#mytags').on("change", function (e) {
           console.log("change " + JSON.stringify({
               val: e.val,
               added: e.added,
               removed: e.removed
           }));

           if (e.added) {
               alert('added: ' + e.added.text + ' id ' + e.added.id)
           } else if (e.removed) {
               alert('removed: ' + e.removed.text + ' id ' + e.removed.id)

           }
       });

   });
bhoward
  • 2,780
  • 4
  • 21
  • 22

2 Answers2

2

There was an issue with your select2 declaration and syntax.

Further more, if you entered any other text, say "eas" or "test", your piece of code reflected that as it is. Check this scenario.

Updated fiddle: http://jsfiddle.net/ZBf5H/

To be specific, you did not give appropriate mapping to your tags. Please find how to access remote data in select 2 from here

The change of code is as below:

$(document).ready(function() {

 var data=[{id:1354,text:'north',restricted:false}, 
           {id:1356,text:'east',restricted:false},
           {id:1357,text:'west',restricted:false},
           {id:1355,text:'south',restricted:false}];

           function format(item) 
              { return item.text; }

        $('#mytags').select2({
            placeholder: 'Search',
            allowClear: true,
            minimumInputLength: 2,
            multiple: true,
            tags: tags,
            tokenSeparators: [','],
            data:{ results: data, text: 'text' },
            formatSelection: format,
            formatResult: format
        });

Let me know if this works for you.

Josh
  • 253
  • 3
  • 11
  • Thanks for the help, but your jsfiddle doesn't show up with any tag preloaded, and it includes the same data twice, once as "tags" and once as "data." If you could, what's the relationship between these two anyways? I was under the impression that tags was the potentially available tags, while data represented those assigned to this particular input - is that not correct? Also, why remove the quotes from the json data? Are they significant? I thought best practice was to include them: http://stackoverflow.com/questions/949449/json-spec-does-the-key-have-to-be-surrounded-with-quotes – bhoward Mar 06 '14 at 04:59
0

Ok... I've got a working solution, but I still don't exactly understand the difference between select2's tags and data options....

JSfiddle: http://jsfiddle.net/7e8Pa/

I'm initializing select2 with a list of all possible tags via the data option from an array, then selecting those for preloading: the initSelection function checks for ids in the and looks them up in the data array (the pre-stored one, not Select2's). Last, new tags may be added (the createSearchChoice does this). To hook this to my server, I'm just going to insert ajax calls where noted below in the on-change event handler (which gets called after createSearchChoice, and can overwrite the field values for the new object set in createSearchChoice).

JS:

function findWithAttr(array, attr, value) {
    for (var i = 0; i < array.length; i += 1) {
        if (array[i][attr] == value) {
            return array[i];
        }
    }
}



$(document).ready(function () {


    function format(item) {
        return item.text;
    }




    $('#mytags').select2({
        placeholder: 'Search',
        minimumInputLength: 2,
        multiple: true,
        //tags: tags,
        tokenSeparators: [','],

        data: {
            results: tags,
            text: 'text'
        },
        initSelection: function (element, callback) {


            var data = [];
            $($('#mytags').val().split(",")).each(function (i) {


                var o = findWithAttr(tags, 'id', this);

                if (o) {
                    data.push({
                        id: o.id,
                        text: o.text
                    });
                } else {
                    console.log("findWithAttr returned none; likely invalid id");
                }
            });
            console.log("data = " + JSON.stringify(data));
            callback(data);
        },
        createSearchChoice: function (term, data) {
            console.log("create");
            if ($(data).filter(function () {
                return this.text.localeCompare(term) === 0;
            }).length === 0) {
                // call $.post() to add this term to the server, receive back id
                // return {id:id, text:term}
                // or detect this shiftiness and do it below in the on-change

                return {
                    id: -1,
                    text: term
                };
            }
        },

        formatSelection: format,
        formatResult: format
    });



    $('#mytags').on("change", function (e) {
        console.log("change " + JSON.stringify({
            val: e.val,
            added: e.added,
            removed: e.removed
        }));

        if (e.added) {
            alert('added: ' + e.added.text + ' id ' + e.added.id);
            //modifying the id here overrides what is assigned above in createSelection
            e.added.id = 5;
        } else if (e.removed) {
            alert('removed: ' + e.removed.text + ' id ' + e.removed.id);

        }
        var selections = (JSON.stringify($('#mytags').select2('data')));
        $('#selectedText').text(selections);

    });

});

HTML:

<script>
    var tags = [{
        "id": 1354,
            "text": "north",

            "restricted": false
    }, {
        "id": 1355,
            "text": "south",

            "restricted": false
    }, {
        "id": 1356,
            "text": "east",

            "restricted": false
    }, {
        "id": 1357,
            "text": "west",

            "restricted": false
    }];
</script>
<p>tags:
    <input type="text" id="mytags" value="1355" style="width:80%" />
</p>
<p>Selected Options: <span id="selectedText"></span>

</p>
<p>Debug: <span id="debug"></span>

</p>
bhoward
  • 2,780
  • 4
  • 21
  • 22