Reputation: 1345
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?
Upvotes: 20
Views: 46134
Reputation: 43815
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 theescapeMarkup
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;
}
};
Upvotes: 0
Reputation: 169
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;
}
};
Upvotes: 16
Reputation: 409
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;
}
};
Upvotes: 23
Reputation: 17178
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.
Upvotes: 0
Reputation:
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;
}
};
Upvotes: 9
Reputation: 24638
Try this:
var optimage = $(opt).data('image'); //or $(opt).attr('data-image')
var $opt = $(
'<span><img src="' + optimage + '" class="img-flag" /> ' + $(opt).text() + '</span>'
);
Upvotes: 3