Search code examples
jqueryjquery-select2jquery-select2-4

Select2: Add and select manual values when using ajax data source


I want to achieve following scenario with select2(4.0.0) and jquery(2.1.4):

  • I have a select box which takes data from external source (end point on java application server)
  • User can either pick one of the returned values or come up with his own value
  • Now when user submits the form and the validation on the server side fails I would like to display the form with all the values provided previously by the user, therefore select box should have the value send to the server.

To achieve that

  • I use ajax from select to query data from the server
  • I use createTag to allow user to create his own values
  • I wanted to use initSelection to prefill selectbox with a value previously added by user.

My code looks like this:

$("select[name='serie']").select2({
    ajax: {
        url: "http://javaendpoit/serie/filter",
        dataType: 'json',
        delay: 250,
        data: function (params) {
          return {
            name: params.term,
            page: params.page
          };
        },
        processResults: function (data, page) {
          return {
            results: $.map(data, function (item) {
              return {
                text: item.name,
                name: item.name,
                id: item.name
              }
            })
          };
        },
        cache: true
      },
      escapeMarkup: function (markup) { return markup; },
      minimumInputLength: 2,
      templateResult: formatRepo,
      templateSelection: formatRepoSelection,
      tags: true,
      createTag: function (tag) {
        return {
          id: tag.term,
          text: tag.term,
          name: tag.term,
          isNew : true
        };
      },
      /* below part is rendered by jsp so that it has the value from previous form submission; if it is initial form render the below part is not included */
      initSelection : function (element, callback) {
            callback({id:"Name",name:"Name","text":"Name"});
      }   
    });

 function formatRepo (serie) {
        if (serie.loading) return serie.text;
        var markup = '<div class="clearfix">' +
        '<div clas="col-sm-10">' +
        '<div class="clearfix">' +
        '<div class="col-xs-12">' + serie.name + '</div>' +
        '</div>';
        markup += '</div></div>';
        return markup;
  }

  function formatRepoSelection (serie) {
    return serie.name;
  }

This works just fine. Meaning that after the submission I can see value Name in the select box and it's the selected value. Nevertheless, if I try to submit this form again, the value is missing in the request.

As suggested in the number of topics here I added following line (see last line).

  /* [...] */
  initSelection : function (element, callback) {
        callback({id:"Name",name:"Name","text":"Name"});
  }   
}).select2("val","Name");

But after adding this the value Name is not even visible in the select2 box.

I have been trying to fix it for few hours now, but somehow cannot find the right solution. I bet I am missing some basic stuff. Plese help!

--- [EDIT]

After adding data I am able to see the value Name even when setting the value with val nevertheless if I resubmit the form this value is still not present in the request.

.select2('data',{id:"Name",name:"Name","text":"Name"})
.select2('val', "Name")

--- [EDIT 2]

In html I use select to create this element.

<select class="form-control" name="serie"></select>

Solution

  • Thanks to Kevin I was able to solve the puzzle. So ultimately I have given up on using initSelection. Instead I just filled select tag with options that should be selected.

    <select class="form-control" id="author" name="author" multiple="multiple">
      <option value="name" selected="selected">name</option>
    </select>
    

    Removed initSelection from select2 definition

    $("select[name='author']").select2({
        ajax: {
            url: "http://javaendpoit/serie/filter",
            dataType: 'json',
            delay: 250,
            data: function (params) {
                return {
                    name: params.term,
                    page: params.page
                };
            },
            processResults: function (data, page) {
                return {
                    results: $.map(data, function (item) {
                        return {
                            text: item.name,
                            name: item.name,
                            id: item.name
                        }
                    })
                };
            },
            cache: true
        },
        escapeMarkup: function (markup) {
            return markup;
        },
        minimumInputLength: 1,
        templateResult: formatRepo,
        templateSelection: formatRepoSelection,
        tags: true,
        createTag: function (tag) {
            return {
                id: tag.term,
                text: tag.term,
                name: tag.term,
                isNew: true
            };
        }
    });
    

    And changed formatRepoSelection to work with values without name attribute.

    function formatRepoSelection(serie) {
        if (serie.name === undefined) {
            return serie.text;
        } else {
            return serie.name;
        }
    }
    

    I guess I could not use name attribute in the formatRepo and could remove the if clause for formatRepoSelection. But this is just a minor fix.