Tagging with AJAX in select2
Asked Answered
L

4

79

I am doing tagging with select2

I have these requirements with select2:

  1. I need to search some tags using select2 ajax
  2. Also I need to use "tags" in select2 which Allows values that are not in the list(Ajax result).

Both the scenarios work independently. But joined together aJax values are only populated. If we type any other values not in the list then it says "no matches found"

My scenario If user type any new value which is not in the list, allow them to make up their own tag.

Any way to make this work?

Lacreshalacrimal answered 9/1, 2013 at 6:50 Comment(0)
O
101

Select2 has the function "createSearchChoice":

Creates a new selectable choice from user's search term. Allows creation of choices not available via the query function. Useful when the user can create choices on the fly, eg for the 'tagging' usecase.

You could achieve what you want by using:

createSearchChoice:function(term, data) {
  if ($(data).filter(function() {
    return this.text.localeCompare(term)===0;
  }).length===0) {
    return {id:term, text:term};
  }
},
multiple: true

Here's a more complete answer that returns a JSON result to an ajax search, and allows tags to be created from the term, if the term returned no results:

$(".select2").select2({
  tags: true,
  tokenSeparators: [",", " "],
  createSearchChoice: function(term, data) {
    if ($(data).filter(function() {
      return this.text.localeCompare(term) === 0;
    }).length === 0) {
      return {
        id: term,
        text: term
      };
    }
  },
  multiple: true,
  ajax: {
    url: '/path/to/results.json',
    dataType: "json",
    data: function(term, page) {
      return {
        q: term
      };
    },
    results: function(data, page) {
      return {
        results: data
      };
    }
  }
});
Overset answered 12/2, 2013 at 21:15 Comment(2)
For those who run into difficulty if using this snippet: the $(data).filter function is where the matching takes place, and this.text is simply the value of the text key in the returned JSON. If you're returning a list of contacts, for example, you will want to check this.name. Also, if you're doing some kind of term-matching in your remote file (/path/to/results.json), you'll simply want to make sure the items being returned have the properties you need, and aren't undefined or badly formatted after being returned from the remote file. (Phew, great answer. Thanks Chris!)Wherefrom
can you please have a look on this question. #35232084Eyeglass
R
39

Select v4

http://jsfiddle.net/8qL47c1x/2/

HTML:

<select multiple="multiple" class="form-control" id="tags" style="width: 400px;">
    <option value="tag1">tag1</option>
    <option value="tag2">tag2</option>
</select>

JavaScript:

$('#tags').select2({
    tags: true,
    tokenSeparators: [','],
    ajax: {
        url: 'https://api.myjson.com/bins/444cr',
        dataType: 'json',
        processResults: function(data) {
          return {
            results: data
          }
        }
    },

    // Some nice improvements:

    // max tags is 3
    maximumSelectionLength: 3,

    // add "(new tag)" for new tags
    createTag: function (params) {
      var term = $.trim(params.term);

      if (term === '') {
        return null;
      }

      return {
        id: term,
        text: term + ' (new tag)'
      };
    },
});

Select v3.5.2

Example with some improvements:

http://jsfiddle.net/X6V2s/66/

html:

<input type="hidden" id="tags" value="tag1,tag2" style="width: 400px;">

js:

$('#tags').select2({
    tags: true,
    tokenSeparators: [','],
    createSearchChoice: function (term) {
        return {
            id: $.trim(term),
            text: $.trim(term) + ' (new tag)'
        };
    },
    ajax: {
        url: 'https://api.myjson.com/bins/444cr',
        dataType: 'json',
        data: function(term, page) {
            return {
                q: term
            };
        },
        results: function(data, page) {
            return {
                results: data
            };
        }
    },

    // Take default tags from the input value
    initSelection: function (element, callback) {
        var data = [];

        function splitVal(string, separator) {
            var val, i, l;
            if (string === null || string.length < 1) return [];
            val = string.split(separator);
            for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
            return val;
        }

        $(splitVal(element.val(), ",")).each(function () {
            data.push({
                id: this,
                text: this
            });
        });

        callback(data);
    },

    // Some nice improvements:

    // max tags is 3
    maximumSelectionSize: 3,

    // override message for max tags
    formatSelectionTooBig: function (limit) {
        return "Max tags is only " + limit;
    }
});

JSON:

[
  {
    "id": "tag1",
    "text": "tag1"
  },
  {
    "id": "tag2",
    "text": "tag2"
  },
  {
    "id": "tag3",
    "text": "tag3"
  },
  {
    "id": "tag4",
    "text": "tag4"
  }
]

UPDATED 2015-01-22:

Fix jsfiddle: http://jsfiddle.net/X6V2s/66/

UPDATED 2015-09-09:

With Select2 v4.0.0+ it became easier.

Select v4.0.0

https://jsfiddle.net/59Lbxvyc/

HTML:

<select class="tags-select" multiple="multiple" style="width: 300px;">
  <option value="tag1" selected="selected">tag1</option>
  <option value="tag2" selected="selected">tag2</option>
</select>

JS:

$(".tags-select").select2({
  // enable tagging
  tags: true,

  // loading remote data
  // see https://select2.github.io/options.html#ajax
  ajax: {
    url: "https://api.myjson.com/bins/444cr",
    processResults: function (data, page) {
      return {
        results: data
      };
    }
  }
});
Registration answered 23/5, 2014 at 17:40 Comment(6)
very Nice Demonstration :) @faostLacreshalacrimal
@faost could you please have a look into this. if possible #35216802Eyeglass
@faost: select2 v4.0.0 in your demo auto complete not work and not filter/find wordAmylopsin
@ಠ_ಠ select2 send search term as query parameter, in my example request looks like this: GET https://api.myjson.com/bins/444cr?q=TEST. But api.myjson.com/bins/444cr is a static URL and it cannot handle query parameters. In real app your backend will use this query parameter "q" to filter results.Registration
@faost: your example not work in 4.0.3 version (latest).Admetus
@Registration myjson.com service is no longer available, maybe use jsonserve.com in your examples instead?Masteratarms
L
5
createSearchChoice : function (term) { return {id: term, text: term}; }

just add this option item

Laissezfaire answered 9/4, 2013 at 7:31 Comment(1)
You should not do that, because if you have existing tag, user will have two choices of same tag, for example 'test' (from database) and 'test' - newly created. You should check if term is already in data.Tysontyumen
F
0

You can make this work, by having your ajax function also return the search term, as the first result in the result list. The user can then select that result as a tag.

Favourite answered 15/1, 2013 at 13:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.