I am using Select2.js(latest version) to implement tokenized tagging in my application. It is working fine except, I am not able to select any item from the suggestions.
I saw few answers in which it was mentioned that we need to include "id" in our configuration. it doesn't seems to be working for me.
My code is :
$("#interest").select2({ ajax: {
url: "get-interests",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
return {
results: data
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
placeholder:{
id: "-1",
text: "Add your interest.."
} ,
tags: true,
tokenSeparators: [',', ' '],
id: function(data) {
alert(JSON.stringify(data));
return data.interestId;
},
templateResult: function(post) {
// return html markup for individual result item
var markup ="";
if(String(post.description) !== 'undefined') {
markup = '<p><b>' + post.text + '</b> : ' + post.description + '</p>';
} else {
markup = '<p><b>' + post.text + '</b></p>';
}
return markup;
},
formatSelection: function(post) {
// This shows up in the select box
return post.text;
}
What I am doing wrong in above configuration?
Contrary to the comment you placed in your code, with Select2 4.0 you do need to add code to the processResults function to convert the returned JSON data to objects with an id property. Normally, the objects should also have a text property, but they don't have to if you supply the templateResult and templateSelection functions.
I saw few answers in which it was mentioned that we need to include
"id" in our configuration. it doesn't seems to be working for me.
Those answers were correct for previous versions of Select2, but with with Select2 v4.0, the id function is no longer supported. See the "The id and text properties are strictly enforced" section on the the "4.0 Anouncement" page:
You can also remove the formatSelection function. With Select2 4.0 it should now be named templateSelection. That means it is not getting called for you, but you probably didn't notice that because your formatSelection function is just doing what is done by default anyway.
The processResults function should return an object with a results property, which is set to an array of objects. Those objects all need to have an id property (but they can have other properties too).
You don't show what your returned data looks like, but judging from your id and templateResult functions, it appears to be an array of objects with the following properties: interestId, text and description. In that case your processResults function could look something like this:
// This builds a new array of new objects.
processResults: function(data, page) {
return {
results: $.map(data, function(post) {
return {
id: post.interestId,
text: post.text,
description: post.description
};
})
};
},
Or this:
// This just adds an `id` property to the objects in the existing array.
processResults: function(data, page) {
$.each(data, function(i, post) {
post.id = post.interestId;
});
return { results: data };
},
Related
The handlebars.js template is generated server side and returned as part of the response.
"<div>{{name}}<small style='color:#999;'><br><code>{{vafm}}</code></small><br><code>{{email}}</code></div>"
.
var t = "";
$('#UniqueId').select2({
ajax: {
url: '/search/endpoint',
dataType: 'json',
processResults: function (data) {
t = data.template;
return {
results: data.results
};
},
},
templateResult: Handlebars.compile(t),
escapeMarkup: function (m) {
return m;
}
});
Unfortunately the rendered part on select2 does not contain the values returned by the data.results
I have located the issue to this line
templateResult: Handlebars.compile(t),
since trying something like
<script>
const template = Handlebars.compile(#Html.Raw(Model.Template));
</script>
and
templateResult: template,
works as expected.
In the last example i pass the template from the model,
but not i need to pass it from the ajax response and achieve the same output.
There are multiple problems:
templateResult expects a callback function, but you are passing a compiled Handlebars template object. It's described here in the select2 docs. So, assuming that you already did the following in the right place:
var t = Handlebars.compile(...)
Then something like this would work:
templateResult: function(data) {
if (!data.id) return data.text;
return $(t({
name: 'example name',
vafm: 'example vafm',
email: 'example email'
}));
The template html must have one enclosing element, so put things in a <div></div>, for example
Your template is missing a <small> opening tag
So let's assume your server sends some JSON like the following. The template for every result is sent along and can be different for every result. Same goes for the template-specific data:
[
{
"id": 1,
"text": "Henry",
"data": {
"vafm": "1234",
"email": "henry#example.com"
},
"template": "<div>{{text}}<br><small>vafm: {{data.vafm}}</small></div><small>email: {{data.email}}</small>"
}, {
"id": 30,
"text": "Tesla Roadster",
"data": {
"price": "$200.000",
"color": "dark red"
},
"template": "<div>{{text}}<br><small>price: {{data.price}}</small></div><small>color: {{data.color}}</small>"
}
]
Together with something like this in your JavaScript, it should work:
$('#UniqueId').select2({
ajax: {
url: '/search/endpoint',
dataType: 'json',
processResults: function(data) {
/** Note: select2 expects "results" to be an array of objects, each containing
* at least "id" (becomes the value) and "text" (displayed text). I made the
* format from the server match that (plus added some more info), so that I don't
* need any conversions except for compiling the template. I do that with
* Array.prototype.map() in this case, but of course a for-loop would work too.
*/
return {
results: data.map(function(e) {
e["template"] = Handlebars.compile(e["template"]);
return e;
})
};
}
},
templateResult: function(el) {
if (!el.id) return el.text;
/* Note: "el" will be just like it came from the server, except for the
* modifications we applied in processResults. We can just pass "el" to
* the compiled template entirely and there, only pick what we need.
*/
return $(el["template"](el));
}
});
I am using the select2 multiple for search box. I am passing these data with JSON and saving it using ajax(JSON stringify).
I just need 2 variables passed, which is the ID(primary key, customized) and the Selection itself.
I managed to save it to the database when only 1 value is selected.
When selecting multiple values, in my console.log, I see something like this
{21,23,25,26}
which is the selection itself.
How do I get it show like this,
Object0->{id:1, selection:21}
Object1->{id:2, selection:23}
Object2->{id:3, selection:25}
Object3->{id:4, selection:26}
Below is the code I am using,
var nature = {
ubtBusinessInfo: businessId, // the primary key
ubtBusinessListing: nature.val() // here is selection
};
Here is the initialization of the select2,
nature
.select2({
allowClear: true,
placeholder: "Filter as you type",
minimumInputLength: 3,
multiple: true,
ajax: {
url: 'home/umkei/info/nature',
dataType: 'json',
quietMillis: 250,
data: function (term, page) {
return { q: term };
},
results: function (data, page) {
return { results: data };
},
cache: true
}
})
nature is defined from(I tried both as below)
var nature = $('[name=nature_business]') OR var nature = $(#nature_business);
I know it must have something to do with the nature.val() usage. Must have been something like array but I dont know how to differentiate/split those data to be key->value pairs.
Thank you.
I got this about last week and thought I'd share my solution.
var nature=[];
var splitnature = nature_business.val().trim().split(',');
var n;
for(n=0; n<=splitnature.length-1;n++){
nature.push({
ubtBusinessListing: splitnature[n],
ubtBusinessInfo: businessId
});
}
TL;DR
To make it clearer, I want to have access to ALL the data in the selected JSON object inside the onItemAdd function. Right now I only have access to _id and name via the config variables.
Ok, so I have a working Selectize.js function grabbing a JSON object from my server and creating the select options.
What I want to know is, can I get anymore data from the existing JSON object inside the "onItemSelect" callback?
The only data I can get directly is the value as specified in the config, which in this case is the "_id" and the $item which i assume is form the labelField in the config, in this case is the name form the JSON data.
How can I get more data than that for the selected item? You see in the render object I use the variable item.sku, how can I access the sku variable in the "onItemAdd" callback?
the data form the server is a json array:
[
{ _id: 'abcd1234', name: 'Sample', sku: '00123' },
{ _id: 'efgh5678', name: 'Sample2', sku: '00124' }
]
My function
// setup select box to add new products to list
$('#buyingGroupAddProducts').selectize({
valueField: '_id',
labelField: 'name',
searchField: 'name',
options: [],
create: false,
closeAfterSelect: true,
render: {
option: function(item, escape) {
return '<div>'+ escape(item.sku) + ': ' + escape(item.name) + '</div>';
}
},
load: function(query, callback) {
if (!query.length) return callback();
$.ajax({
url: '/buying/products-search',
type: 'GET',
dataType: 'json',
data: {
q: query
},
error: function() {
callback();
},
success: function(res) {
callback(res);
}
});
},
onItemAdd: function(value, $item) {
// DO the thing
console.log($item);
}
});
SelectizeJS site: http://selectize.github.io/selectize.js/
a hack to solve your problem : inside onItemAdd function you can access all your JSON : this.options gives you all the selectize options, so now you have the value and the complete JSON, you can easily find back the item in your json that corresponds to the value selected. I can complete my answer if you provide a use case in plunker.
Id' like to be able to get names from my sharepoint list, these names are added with a peoplepicker, and stored with the field names 'People' and 'Responsible', they are of type 'person or group' in SharePoint. In my Service file I have this:
this.getPeople = function () {
var deferred = $.Deferred();
var restQueryUrl = appweburl + "/_api/lists/getByTitle('RisikoAnalyse')/items?$select=People/Title,Responsible/Title&$expand=People/Title,Responsible/Title";
var executor = new SP.RequestExecutor(appweburl);
executor.executeAsync({
url: restQueryUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data, textStatus, xhr) {
deferred.resolve(JSON.parse(data.body));
},
error: function (xhr, textStatus, errorThrown) {
deferred.reject(JSON.stringify(xhr));
}
});
return deferred;
};
I get two fields from this, on 'People' which is the multiple value field, and one 'Responsible' where only one value is allowed.
In other words, the first field will have several names in it, and the other will only have one name in it.
In my controller I have:
$.when(SPService.getPeople())
.done(function (jsonObject) {
angular.forEach(jsonObject.d.results, function (obj) {
$scope.peopleList.push({
people: obj.People.Title,
responsible: obj.Responsible.Title
});
//$scope is not updating so force with this command
if (!$scope.$$phase) {
$scope.$apply();
}
});
});
Here I iterate over all objects in 'jsonObject.d.results', and push them to my list of people, 'PeopleList'.
This works for the single value 'Responsible' field, but not the multiple value 'People' field, I'm thinking I have to iterate over the objects inside the 'people' field, but I don't know where or how to do this in an effective way.
In short: How can I get the multiple values into my peopleList?
Since SharePoint REST service returns multi-valued User field in the following JSON format:
{
results:
[ { Title: "John Doe"}],
[ { Title: "Jane Doe"}]
}
you could extract people titles as shown below:
var peopleTitles = item.People.results.map(function(p){ return p.Title});
Modified example for a controller
angular.forEach(jsonObject.d.results, function (obj) {
var peopleTitles = typeof obj.People.results != 'undefined' ? obj.People.results.map(function(p){ return p.Title}) : [];
$scope.peopleList.push({
people: peopleTitles,
responsible: obj.Responsible.Title
});
});
I am trying to get select2 to work with an external json-file:
The json-file looks like this (it is called data.json and is in the root directory of my Website):
{"laender":[
{
"Land" : "Ägypten",
"kurz" : "EG",
"Fahne" : "aegypten"
},
{
"Land" : "Andorra",
"kurz" : "AN",
"Fahne" : "andorra"
}
]}
The Javascript Looks like this:
$(document).ready(function($) {
function formatValues(data) {
return data.Land + ' ' + data.Fahne;
}
$('#countrySelect').select2({
ajax: {
dataType: "json",
url: "data.json",
results: function (data) {
return {results: data};
}
},
formatResult: formatValues
});
(As mentioned here: Select2 load data with Ajax from file).
The Output in HTML is a simple
<div id="countrySelect"></div>
But I can't get it to work. I tried so many things but nothing happens. Also I am rather new to json and Ajax.
Thanks for any help in advance!
Dietmar
your javascript code is for old version select2 below 4.0.0. if you using select2 4.0.0, then you must using processResult instead of result.
try to change these lines
results: function (data) {
return {results: data};
}
to like this
processResults: function (data) {
return {results: data};
}
for additional info, select2 4.0.0 doesn't support input hidden anymore. so, your #countrySelect must be select element rather than hidden input.
sorry my bad english
reference:
select2 4.0.0 ajax documentation
Your keys in json is:
"Land", "kurz", "Fahne",
but select2 in this case expect:
"id", "text"
to make: <option value="id"> text </option>
You should use map function:
processResults: function(data){
return {
results: $.map(data, function(smthg){
return { id: smthg.kurz, text: smthg.Fahne }
})
};
}
its example, i don't know which values You want use, and i use json like:
[
{"id_pr":"1252","pr":"aaa"},
{"id_pr":"1253","pr":"bbb"}
...
]
and it works, but
i didn't try:
{ laender: [
{"id_pr":"1252","pr":"aaa"},
{"id_pr":"1253","pr":"bbb"}
]}