How to append an icon to selected item in select2?
Asked Answered
P

11

9

I'm using fontawesome, and I want to add or remove an icon to the selected item. So I did this: http://jsbin.com/nasixuro/7/edit (Thanks to @Fares M.)

JS

$(document).ready(function () {

    function format_select2_icon(opti) {
        if (!opti.id) return opti.text; // optgroup

        if ($(opti.element).data('icon') == "1") {
            return opti.text + " <i class='fa fa-check'></i>";
        } else {
            return opti.text;
        }
    }

    $("#sel").select2({
        escapeMarkup: function(m) { return m; },
        formatResult: format_select2_icon,
        formatSelection: format_select2_icon
    });

    $("#addok").click(function() {
        actual_value = $("#sel").find(':selected').text();

        if (actual_value.indexOf(" <i class='fa fa-check'></i>") > -1){
            alert("asd");
            return;
        }

        newtext = actual_value + " <i class='fa fa-check'></i>";
        $("#sel").find(':selected').text(newtext).change();
    });

  $("#removeok").click(function() {

        actual_value= $("#sel").find(':selected').text();
        indexOk=actual_value.indexOf(" <i class='fa fa-check'></i>");

        if (indexOk > -1){
            newtext =actual_value.substring(0, indexOk);
            $("#sel").find(':selected').text(newtext).change();
            return;
        }

    });
});

HTML

 <select id="sel" style="width: 100%">
    <option value="1">Hello</option>
    <option value="2" data-icon="1">Friends</option>
    <option value="3">Stackoverflow</option>
</select>
<br><br>
<button id="addok">Add <i class='fa fa-check'></i></button>
<button id="removeok">Remove <i class='fa fa-check'></i></button>

As you see, you can add or remove the icon in Hello and Stackoverflow items, but in Friends (that is the option formated with formatSelection and formatResult), does not remove the icon, and if you try to add the icon, the appends another one to the existing.

Do you have any idea to solve this?

Petrarch answered 13/5, 2014 at 20:1 Comment(0)
P
6

Simply replacing < by &lt; in the option and removing format functions:

<select id="sel" style="width: 100%">
    <option value="1">Hello</option>
    <option value="2">Friends &lt;i class='fa fa-check'>&lt;/i></option>
    <option value="3">Stackoverflow</option>
</select>

You can test it here: http://jsbin.com/nasixuro/11/edit

Petrarch answered 14/7, 2014 at 15:8 Comment(1)
This jsbin no longer works as the source files for select2 js and css are 404s. Can you update with a CDN that serves those versions still?Harms
S
11

I think there's two ways to achieve that:

  1. The first solution is the better one,

    you can make it work just by defining an escapeMarkup function in select2 options, and this function must return the same data received as input parameter without any changes.

    all what you need is:

    $("#sel").select2({
        escapeMarkup: function(m) { 
           return m; 
        }
    });
    

    here's a working example: http://jsbin.com/nasixuro/3/edit

  2. The second one, make a small changes in select2.js file.

    after inspecting the select2.js, i found the function which updates the text, and there was a little problem, select2.js plugin escapes html to prevent js injection, so to get it work as you expect you have to avoid escaping html and use .html() function from jquery api to insert your html instead of .append() function used in updateSelection function of select2.js.

    here's the function i'm talking about:

    // single
    updateSelection: function (data) {
    
        var container=this.selection.find(".select2-chosen"), formatted, cssClass;
    
        this.selection.data("select2-data", data);
    
        container.empty();
        if (data !== null) {
            formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup);
        }
        if (formatted !== undefined) {
            container.append(formatted);
        }
        cssClass=this.opts.formatSelectionCssClass(data, container);
        if (cssClass !== undefined) {
            container.addClass(cssClass);
        }
    
        this.selection.removeClass("select2-default");
    
        if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
            this.container.addClass("select2-allowclear");
        }
    },
    

    delete this:

    if (data !== null) {
         formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup);
    }
    

    and change:

    if (formatted !== undefined) {
         container.append(formatted);
    }
    

    to:

    if (data !== undefined) {
         container.html(data.text);
    }
    

    this is a dirty solution in my opinion.

    For the Remove action use this js code:

    $("#removeok").click(function() {
    
        actual_value= $("#sel").find(':selected').text(), 
        indexOk =actual_value.indexOf(" <i class='fa fa-check'></i>");
        if (indexOk > -1){
            newtext =actual_value.substring(0, indexOk);
            $("#sel").find(':selected').text(newtext).change();
            return;
        }
    
    });
    
Schopenhauerism answered 15/5, 2014 at 23:41 Comment(1)
Why use JS when CSS can do it !? I find it rather complicated and it uses more resources in browser.Repulsion
P
6

Simply replacing < by &lt; in the option and removing format functions:

<select id="sel" style="width: 100%">
    <option value="1">Hello</option>
    <option value="2">Friends &lt;i class='fa fa-check'>&lt;/i></option>
    <option value="3">Stackoverflow</option>
</select>

You can test it here: http://jsbin.com/nasixuro/11/edit

Petrarch answered 14/7, 2014 at 15:8 Comment(1)
This jsbin no longer works as the source files for select2 js and css are 404s. Can you update with a CDN that serves those versions still?Harms
C
3

Manbe you can use the select2 parameter : formatResult or formatSelection like below

$(document).ready(function () {

    $("#sel").select2();

    $("#addok").click(function() {
       $("#sel").select2({
          //formatResult: format
          formatSelection: format
          //escapeMarkup: function(m) { return m; }

       });
    });
});

function format(state) {
   if (!state.id) return state.text; 
   return "<i class='fa fa-check'></i>" + state.text;
}

JSBIN

Cockrell answered 15/5, 2014 at 13:50 Comment(2)
Thanks! But I need only with the selected item. Do you have any idea?Petrarch
I thought Fares M. has the best solutionCockrell
S
3

You need not do the DOM manipulation manually

var icon_checked = "<i class='fa fa-check'></i>";

function format(opt) {
    var selection = this.element.select2("val");

    if (opt.id === selection) {
        return opt.text + icon_checked;
    }
    return opt.text;
}   

$("#sel").select2({
    formatResult: format
});

Basically this.element returns you the select element instance, on which you can run .select2("val") to get the selected value.

Compare that with the id of the object, if it is true then give the HTML with checkbox else return plain text. I think this is what you were trying to achieve.

Here is a Working fiddle, I think this is what you were trying to acheive

Subclinical answered 18/7, 2014 at 12:52 Comment(0)
L
2

You can`t add tags inside option. Try to set option font as font-family: "myfontawesome", arial; and add special character instead css replacement.

Levator answered 13/5, 2014 at 20:14 Comment(0)
B
1

I think your problem is that you can't style values or add html to items that are in dropdown selects like you are trying to...it's pure text.

newtext = actual_value + "wat";

See how your fiddle works when I remove the html and just add plaintext:

I also might suggest looking here.

Bartley answered 13/5, 2014 at 20:7 Comment(0)
S
1

If you want the icon to display, you need to target the HTML element and insert HTML not TEXT. pretty much like this:

$(document).ready(function () {

    $("#sel").select2();

    $("#addok").click(function() {
        actual_value = $("#sel").find(':selected').text();

        if (actual_value.indexOf(" <i class='fa fa-check'></i>") > -1){
            alert("asd")
            return
        }

        newtext = actual_value + "<i class='fa fa-check'></i>";
        $("#s2id_sel").find('.select2-chosen').html(newtext);
    });
});

See http://jsfiddle.net/S9tE3/

BUT. The HTML element you need to target, from what i can see, is $('s2id_'+[current element id]). s2 i guess for SELECT2 and id_. So your select is id="sel", which means $('s2id_sel'). Also note that you need to find which one is chosen. It, conveniently enough, has a ".select2-chosen" class which makes it kinda easy to target.

This won't change the value, just the LOOK which is I think what you're exactly trying to do.

Hope that helps

Spandau answered 15/5, 2014 at 21:22 Comment(0)
P
1

Replace this code

  <select id="sel" style="width: 100%">
       <option value="1">Hello</option>
       <option value="2" data-icon="1">Friends</option>
       <option value="3">Stackoverflow</option>
  </select>

and put this code

<select id="sel" style="width: 100%">
       <option value="1">Hello</option>
       <option value="2">Friends</option>
       <option value="3">Stackoverflow</option>
  </select>
Portion answered 17/7, 2014 at 6:23 Comment(1)
Can you explain your answer? As it's currently written it's not clear how this little change helps to solve OP's problem.Fruition
B
1

I changed a little code to check your data-icon

   $("#addok").click(function() {
        actual_value = $("#sel").find(':selected').text();
       if($("#sel").find(':selected').data('icon') == '1')  
         {
           alert("asd");
           return}

Set data-icon = 0 to prevent it generate icon from format_select2_icon and remove icon.

 if($("#sel").find(':selected').data('icon') == '1')  {
          $("#sel").find(':selected').data('icon','0') ;
         $(".select2-chosen").text(actual_value).change();
        }

See: http://jsbin.com/nasixuro/18/edit

Hope that helped for you.

Burcham answered 20/7, 2014 at 11:16 Comment(0)
R
0

With fontawesome icon, you can use the following :

.select2-results__option[aria-selected=true]::before {
    content: "\f0c9";
    font: normal normal normal 14px/1 FontAwesome;
    color: rbg(255,0,0);
}

There is text-equivalent of each icon : http://fortawesome.github.io/Font-Awesome/cheatsheet/

Or if you have gif for example, it works very well simply with your image as CSS background like this :

.select2-results__option[aria-selected=true] {
    background: url('path/to/image.gif') no-repeat 10px 10px;
}

Here is the result :

dropdown select with gif as icon

Repulsion answered 17/8, 2017 at 18:33 Comment(0)
F
0

With Bootstrap Glyphicons you can add the following to your CSS

.select2-results__option[aria-selected=true]::after {
    font-family: "Glyphicons Halflings";
    content: "\e013";
}

and glyphicon-ok will be appended to each selected item.

Look in Bootstrap cheatsheet for icon codes.

Fruition answered 29/12, 2017 at 11:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.