20

This is what select2.github.io gives you:

function addIcons(opt) {
    if (!opt.id) {
        return opt.text;
    }
    var $opt = $(
            '<span><img src="/images/flags/' + opt.element.value.toLowerCase() + '.png" class="img-flag" /> ' + opt.text + '</span>'
            );
    return $opt;
}

I'd like to add a data-image attribute to my options:

<option value="flag" data-image="/images/flags/flag.png">Country 1</option>

and log it in the function:

function addIcons(opt) {
    if (!opt.id) {
        return opt.text;
    }

    var optimage = opt.attr('data-image');
    var $opt = $(
            '<span><img src="/images/flags/' + optimage + '" class="img-flag" /> ' + opt.text + '</span>'
            );
    return $opt;
}

Sadly, a simple console.log(opt); doesn't return anything in the function, so I can't see if I can access my data-image attribute. The above block of code returns an error, so this obviously doesn't work. Any suggestions on this matter?

rishal
  • 3,230
  • 3
  • 22
  • 29
Warre Buysse
  • 1,335
  • 4
  • 21
  • 39

6 Answers6

22

Solved using attr and tested on Select2 4.0.6-rc.0.

$(".class").select2({
    templateResult: formatState,
    templateSelection: formatState
});

function formatState (opt) {
    if (!opt.id) {
        return opt.text.toUpperCase();
    } 

    var optimage = $(opt.element).attr('data-image'); 
    console.log(optimage)
    if(!optimage){
       return opt.text.toUpperCase();
    } else {                    
        var $opt = $(
           '<span><img src="' + optimage + '" width="60px" /> ' + opt.text.toUpperCase() + '</span>'
        );
        return $opt;
    }
};
JSTL
  • 808
  • 1
  • 14
  • 25
16

If optimage returns "undefined" try my sample: its working fine:

$("#selectUserForChat").select2({
  templateResult: addUserPic,
  templateSelection: addUserPic
});

function addUserPic(opt) {
  if (!opt.id) {
    return opt.text;
  }
  var optimage = $(opt.element).data('image');
  if (!optimage) {
    return opt.text;
  } else {
    var $opt = $(
      '<span class="userName"><img src="' + optimage + '" class="userPic" /> ' + $(opt.element).text() + '</span>'
    );
    return $opt;
  }
};
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
9

I solved problem with this code: var optimage = $(opt.element).data('image');

$(".category").select2({
            templateResult: formatState,
            templateSelection: formatState
        });
        function formatState (opt) {
            if (!opt.id) {
                return opt.text;
            }               
            var optimage = $(opt.element).data('image'); 
            if(!optimage){
                return opt.text;
            } else {                    
                var $opt = $(
                    '<span><img src="' + optimage + '" width="23px" /> ' + opt.text + '</span>'
                );
                return $opt;
            }

        };
3

Try this:

var optimage = $(opt).data('image'); //or $(opt).attr('data-image')
var $opt = $(
    '<span><img src="' + optimage + '" class="img-flag" /> ' + $(opt).text() + '</span>'
);
PeterKA
  • 24,158
  • 5
  • 26
  • 48
0

Not necessarily related to the question, but in my case it wasn't working because if you are using Select 2 < 4.0, templateResult and templateSelection does not exist. Use formatResult and formatSelection instead.

Lucas Bustamante
  • 15,821
  • 7
  • 92
  • 86
0

Every single answer here is incorrect as it exposes your application to an XSS vulnerability when returning a jQuery object to select2. Let's read the docs and find out why:

Built-in escaping

By default, strings returned by templateResult are assumed to contain only text and will be passed through the escapeMarkup function, which strips any HTML markup.

If you need to render HTML with your result template, you must wrap your rendered result in a jQuery object. In this case, the result will be passed directly to jQuery.fn.append and will be handled directly by jQuery. Any markup, such as HTML, will not be escaped and it is up to you to escape any malicious input provided by users.

Looking at the other answers, they all have the fatal flaw of not escaping the text before passing it back. Instead the correct code should look like this (assuming a proper escape function, I used lodash in my circumstance):

$(".class").select2({
    templateResult: formatState,
    templateSelection: formatState
});

function formatState (opt) {
    if (!opt.id) {
        return opt.text;
    } 

    var optimage = $(opt.element).attr('data-image'); 
    if(!optimage) {
       // This is safe, since you're returning a string
       return opt.text;
    } else {
       // Create an individual image element to properly escape the src url
       var img = $("<img width='60px'>");
       img.attr("src", optimage);

       // And remember to escape the text we're outputing
       var $opt = $(
         '<span>' +
         img.prop('outerHTML'); +
         '" width="60px" /> ' + 
         escape(opt.text) + 
         '</span>'
       );
       return $opt;
    }
};
Gavin Miller
  • 43,168
  • 21
  • 122
  • 188