How to set ordering for default selected value in jQuery select2 remote select box?

Viewed 272

I customized the select2 plugin to display default selected values. I applied the select2 remote select box in the session create and edit page. When I create a session and select multiple speakers from the dropdown it displayed as they are selected.

Create page: enter image description here

But when I edit another field for that session then the selected speakers are not displaying in order as they inserted

Edit page: enter image description here

here is my jQuery code snippet:

$(".jsRemoteSelectBox").each(function (index, element) {
        if ($(element).data("isprocessed") != "1" && $(element).attr("isprocessed") != 1) {
            $(element).data("isprocessed", "1");
            $(element).attr("isprocessed", "1");
            select2SelectedResult = [];
            if ($(element).data("defaultvalue") != undefined) {
                select2SelectedResult = $(element).data("defaultvalue");
            }
            oOptionHtml = [];
            var oTargetControl = $(element).data('targetcontrol');
            $(element).select2({
                dropdownAutoWidth: true,
                allowClear: ($(element).data('allowclear') == "True" ? true : false),
                closeOnSelect: ($(element).data('iscloseonselect') == "True" ? true : false),
                width: '100%',
                placeholder: ($(element).data('placeholder') != undefined ? $(element).data('placeholder') : "Type to search"),
                ajax:
                {
                    url: $(element).data('url'),
                    type: "POST",
                    dataType: 'json',
                    data: function (params) {
                        return {
                            search: params.term,
                            pageResult: ($(element).data('pageresult') != undefined ? $(element).data('pageresult') : 10),
                            page: params.page,
                            notIn: (oTargetControl != undefined ? ($.isArray($("#" + oTargetControl).val()) ? $("#" + oTargetControl).val().join(",") : $("#" + oTargetControl).val()) : ($(element).data('fixedvalue') != undefined ? $(element).data('fixedvalue') : ""))
                        };
                    },
                    processResults: function (data, params) {
                        params.page = params.page || 1;

                        return {
                            results: data.items,
                            pagination: {
                                more: (params.page * ($(element).data('pageresult') != undefined ? $(element).data('pageresult') : 10)) < data.total_count
                            }
                        };
                    },
                    cache: true
                },
                escapeMarkup: function (markup) { return markup; },
                minimumInputLength: ($(element).data('minlength') != undefined ? $(element).data('minlength') : 3),
                //templateResult: formatResult,
                templateResult: function (optionResult) {
                    if (optionResult.loading) return optionResult.text;
                    oOptionHtml = [];
                    oOptionHtml.push("<div class='select2-result-repository clearfix'>");
                    if ($(element).data("isimagedisplay") == "True") {
                        oOptionHtml.push("<div class='select2-result-repository__avatar'>");
                        oOptionHtml.push("<img src='" + optionResult.imageurl + "' />");
                        oOptionHtml.push("</div>");
                    }
                    oOptionHtml.push("<div class='select2-result-repository__meta'>");
                    oOptionHtml.push("<div class='select2-result-repository__title'>");
                    oOptionHtml.push(optionResult.full_name);
                    oOptionHtml.push("</div>");
                    oOptionHtml.push("</div>");
                    if ($(element).data("isdescriptiondisplay") == "True") {
                        oOptionHtml.push("<div class='select2-result-repository__description'>");
                        oOptionHtml.push(optionResult.description);
                        oOptionHtml.push("</div>");
                    }
                    oOptionHtml.push("</div>");

                    return oOptionHtml.join(" ");
                },
                templateSelection: formatResultSelection,
                data: select2SelectedResult
            });
            if (select2SelectedResult.length > 0) {
                $(element).val(select2SelectedResult.select('x.id'));
                $(element).trigger('change');
            }
        }
    });

Generated Html code on create page is:

<div class="row">
    <div class="col-md-12 form-group">
        <label>Select Speaker</label>

        <select class="jsRemoteSelectBox form-control select2-hidden-accessible" data-allowclear="True" data-iscloseonselect="True" data-isdescriptiondisplay="False" data-isimagedisplay="True" data-minlength="3" data-pageresult="10" data-placeholder="Type to search speaker" data-targetcontrol="jsClientID" data-url="/Speakers/SearchSpeakers" id="SpeakerIDs" multiple="" name="SpeakerIDs" isprocessed="1" data-select2-id="SpeakerIDs" tabindex="-1" aria-hidden="true">
        </select>
        <span class="select2 select2-container select2-container--default select2-container--focus" dir="ltr" data-select2-id="6" style="width: 100%;">
            <span class="selection">
                <span class="select2-selection select2-selection--multiple" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1" aria-disabled="false">
                    <ul class="select2-selection__rendered">
                        <li class="select2-search select2-search--inline">
                            <input class="select2-search__field" type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="none" spellcheck="false" role="searchbox" aria-autocomplete="list" placeholder="Type to search speaker" style="width: 1238px;">
                        </li>
                    </ul>
                </span>
            </span>
            <span class="dropdown-wrapper" aria-hidden="true"></span>
        </span>
        <div>
            <small>Usage: Enter at least three characters to get speakers name suggestions. Select a value to continue adding more speakers.</small>
        </div>

        <span class="field-validation-valid red" data-valmsg-for="SpeakerIDs" data-valmsg-replace="true"></span>
    </div>
</div>

Generated Html code on Edit page is:

<div class="row">
    <div class="col-md-12 form-group">
        <label>Select Speaker</label>

        <select class="jsRemoteSelectBox form-control select2-hidden-accessible" data-allowclear="True" data-defaultvalue="[{&quot;id&quot;:&quot;2&quot;,&quot;text&quot;:&quot;Angela  Xavier (Senior Exclusive Head)&quot;,&quot;ImageUrl&quot;:&quot;cf0fab51-84af-43b6-9c4b-7e96227f4e95_images.jpg&quot;,&quot;SessionID&quot;:1056},{&quot;id&quot;:&quot;1&quot;,&quot;text&quot;:&quot;Jon Patel ()&quot;,&quot;ImageUrl&quot;:&quot;7844b969-e793-4af3-899c-0d28bc97da18_download_(2).png&quot;,&quot;SessionID&quot;:1056},{&quot;id&quot;:&quot;3&quot;,&quot;text&quot;:&quot;Haresh Yadav ()&quot;,&quot;ImageUrl&quot;:&quot;28937477-3e2d-4166-aad8-758ffe6ad17b_Beacon_logo_FINAL_white_&amp;_green.jpg&quot;,&quot;SessionID&quot;:1056}]" data-iscloseonselect="True" data-isdescriptiondisplay="False" data-isimagedisplay="True" data-minlength="3" data-pageresult="10" data-placeholder="Type to search speaker" data-targetcontrol="jsClientID" data-url="/Speakers/SearchSpeakers" id="SpeakerIDs" multiple="" name="SpeakerIDs" isprocessed="1" data-select2-id="SpeakerIDs" tabindex="-1" aria-hidden="true">
            <option value="2" data-select2-id="17">Angela  Xavier (Senior Exclusive Head)</option>
            <option value="1" data-select2-id="18">Jon Patel ()</option>
            <option value="3" data-select2-id="19">Haresh Yadav ()</option>
        </select>
        <span class="select2 select2-container select2-container--default select2-container--focus" dir="ltr" data-select2-id="16" style="width: 100%;">
            <span class="selection">
                <span class="select2-selection select2-selection--multiple" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="-1" aria-disabled="false">
                    <ul class="select2-selection__rendered">
                        <span class="select2-selection__clear" title="Remove all items" data-select2-id="23">×</span>
                        <li class="select2-selection__choice" title="Angela  Xavier (Senior Exclusive Head)" data-select2-id="20">
                            <span class="select2-selection__choice__remove" role="presentation">×</span>Angela  Xavier (Senior Exclusive Head)
                        </li>
                        <li class="select2-selection__choice" title="Jon Patel ()" data-select2-id="21">
                            <span class="select2-selection__choice__remove" role="presentation">×</span>Jon Patel ()
                        </li>
                        <li class="select2-selection__choice" title="Haresh Yadav ()" data-select2-id="22">
                            <span class="select2-selection__choice__remove" role="presentation">×</span>Haresh Yadav ()
                        </li>
                        <li class="select2-search select2-search--inline">
                            <input class="select2-search__field" type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="none" spellcheck="false" role="searchbox" aria-autocomplete="list" placeholder="" style="width: 0.75em;">
                        </li>
                    </ul>
                </span>
            </span>
            <span class="dropdown-wrapper" aria-hidden="true"></span>
        </span>
        <div>
            <small>Usage: Enter at least three characters to get speakers name suggestions. Select a value to continue adding more speakers.</small>
        </div>

        <span class="field-validation-valid red" data-valmsg-for="SpeakerIDs" data-valmsg-replace="true"></span>
    </div>
</div>

Please help me with this issue.

2 Answers

As per my understanding, you need to add one Sequence field in the model.

Your model should be like this.

public string id { get; set; } // id for drop-down value
public string text { get; set; } // text for drop-down text visible in select control
public int? Sequence { get; set; } // this is the new filed you have to manage when you select multiple option in drop-down and store in db level.

after then need to change you're select2 partial helper

if (Model.DefaultSelectedValue != null && Model.DefaultSelectedValue.Count > 0)
{
        HtmlAttributes.Add("data-defaultValue", JsonConvert.SerializeObject(Model.DefaultSelectedValue.OrderBy(x=>x.Sequence),
        Formatting.Indented));
}

Note: I've also built the same select2 helper but not much like you and I also facing the issue while inserting if I'm select value like 2,5,1,4 while edit values show 1,2,4,5.

if you still face the issue let me know so we can connect.

its not an easier solution, here a sample showing what you want (event on select selecting, unselect unselecting):

$('#example').select2();

$('#example').on("select2:selecting select2:unselecting", function (evt) {
    var _id = evt.params.args.data._resultId.match(/select2-(\w+)-result/)[1];
    var ul = $(`ul#select2-${_id}-container`)
    var tmpord = ul.children('li').map((idx, elm) => CSS.escape(elm.title)).get()
    tmpord.push(CSS.escape(evt.params.args.data.text))
    ul.data('tmpord', tmpord)
}).on("select2:select select2:unselect", function (evt) {
    var _id = evt.params.data._resultId.match(/select2-(\w+)-result/)[1];
    var ul = $(`ul#select2-${_id}-container`);
    ;(ul.data('tmpord')||[]).forEach(tp => {
        var li = ul.children(`li[title="${tp}"]:contains("${tp}")`)
        li.detach().appendTo(ul)
    })
});
<html>
  <body>
    <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

<select id="example" multiple="multiple" style="width: 300px">
    <option value="Apple">Apple</option>
    <option value="Bat">Bat</option>
    <option value="Cat">Cat</option>
    <option value="Dog">Dog</option>
    <option value="Elephant">Elephant</option>
    <option value="View/Exposure">View/Exposure</option>
    <option value="View / Exposure">View / Exposure</option>
    <option value="Dummy - Data">Dummy - Data</option>
    <option value="Dummy-Data">Dummy-Data</option>
    <option value="Dummy:Data">Dummy:Data</option>
    <option value="Dummy(Data)">Dummy(Data)</option>    
</select>

  </body>
</html>

it is using the internal undocumented _resultId property its a hack, there's no guarantee this property will always be there

a solution with data from json or array:

    var sampleArray = [
    {id: 0, text: 'enhancement'},
    {id: 1, text: 'bug'},
    {id: 2, text: 'duplicate'},
    {id: 3, text: 'invalid'},
    {id: 4, text: 'wontfix'}];

    $("#e10").select2({
      data: sampleArray
    });
    
        $('#e10').on("select2:selecting select2:unselecting", function(evt) {
      var _id = evt.params.args.data._resultId.match(/select2-(\w+)-result/)[1];
      var ul = $(`ul#select2-${_id}-container`)
      var tmpord = ul.children('li').map((idx, elm) => CSS.escape(elm.title)).get()
      tmpord.push(CSS.escape(evt.params.args.data.text))
      ul.data('tmpord', tmpord)
    }).on("select2:select select2:unselect", function(evt) {
      var _id = evt.params.data._resultId.match(/select2-(\w+)-result/)[1];
      var ul = $(`ul#select2-${_id}-container`);;
      (ul.data('tmpord') || []).forEach(tp => {
        var li = ul.children(`li[title="${tp}"]:contains("${tp}")`)
        li.detach().appendTo(ul)
      })
    });
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

<input type="hidden" id="e10" multiple="multiple" style="width:300px" />

Related