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"}
]}
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 cannot get the items of an JSON array within an JSON object. Here's what my JSON looks like:
[
{
"category":9,
"channels":[
{
"id":5,
"title":"MYTITLE",
"active":true,
"recent":true,
"image":"/arts/736c1ad4-2dbe-40a6-859d-8dba89c26ec2.jpg",
"recent_tracks":{
"vip":"https://api.xyzsite.com/recent_tracks/vip-3.json",
"free":"https://api.xyzsite.com/recent_tracks/free-3.json"
},
"additional_vip_channels":[
{
"channel_name":"vip-3a",
"recent_tracks_uri":"https://api.xyzsite.com/recent_tracks/vip-3a.json",
"streams":{
"320":"http://streams.xyzsite.com/api/914/320/stream",
"64":"http://streams.xyzsite.com/api/914/64/stream",
"192":"http://streams.xyzsite.com/api/914/192/stream"
}
}
],
"streams":{
"free":"http://streams.xyzsite.com/api/31/56/stream",
"free_56":"http://streams.xyzsite.com/api/31/56/stream",
"free_128":"http://streams.xyzsite.com/api/31/128/stream",
"320":"http://streams.xyzsite.com/api/33/320/stream",
"64":"http://streams.xyzsite.com/api/33/64/stream",
"192":"http://streams.xyzsite.com/api/33/192/stream"
}
},
I use the following code to get the values:
$.getJSON('https://api.xyzsite.com/channels.json', function(response) {
$.each(response, function (index, value) {
var catId = value.category;
$.each(value.channels, function (index, value) {
XYZApp.channels.push({
categoryId: catId,
id: value.id,
name: value.title,
image: value.image,
recent_tracks: {
vip: value.recent_tracks.vip,
free: value.recent_tracks.free
},
streams: {
free_128: value.streams.free_128,
member_320: value.streams["320"],
member_64: value.streams["64"],
member_192: value.streams["192"]
}
});
console.log(value.additional_vip_channels);
});
});
}).
then ...
I can get the values, but I cannot read the additional_vip_channels array within the .each jQuery function. I already tried:
value.additional_vip_channels.channel_name
value.additional_vip_channels[0].channel_name
value.additional_vip_channels["0"].channel_name
but none of them work.
And the log output is also here:
How can I get the channel_name and other data in additional_vip_channels?
I believe that you would want:
channels[0]['additional_vip_channels'][0]['channel_name']
Equally, this should work: (just a different way of selecting)
channels[0].additional_vip_channels[0].channel_name
Hope that helps and works :)
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.
I am in desperate need of some help from JavaScript experts. I have spent the last 7 hours trying hundreds of combinations of code to get a basic Tag selection input field to work with the library x-editable and select2.
I am building a Project Management app which is going to have Project Task data shown in a popup Modal Div. In the Task Modal, all Task fields will be editable with in-line edit-in-place capability using AJAX.
I am using:
the jQuery edit in place library called X-Editable - http://vitalets.github.io/x-editable/
The drop down selection jQuery library Select2 - https://select2.github.io/
The jQuery MockAjax library to allow simulating AJAX request responses. https://github.com/jakerella/jquery-mockjax
I have setup a basic JSFiddle demo to experiment with just for this StackOverflow question. I don't have the thousands of lines of code from my actual application , however I do have majority of the 3rd part libraries that are being used included into the page. THe reason is to make sure that none of them are interfering with the results.
JSFiddle Demo: http://jsfiddle.net/jasondavis/Lusbqfhs/
The Goal:
Setup X-editable and Select2 on a Field to allow users to select and enter in Tags for a Project Task.
Fetch available Tag records from a backend server which will return a JSON response with Tag ID number and Tag Name and use this data to populate the Selection2 input field to allow a user to select multiple Tags.
Allow user to also type in a NEW tag and it will post and save the new Tags to the backend as well!
When tags are selected and the save button is clicked, it will save the list of selected Tags bu ID number back to a database.
Problems:
Now I have tried hundreds of variations of options and code combinations from my research in the past 7 hours. I cannot seem to get this basic functionality to work and majority of the examples I have found do not seem to work correctly anymore!
On this demo page for the library x-editable http://vitalets.github.io/x-editable/demo-plain.html?c=inline near the bottom of the examples in the table where it says Select2 (tags mode) that functionality is what I need! I just need it to load the available tags from an AJAX request and all the docs claim it can do this with no problem at all!
This is the Documentation section from X-Editable for Select2 fields - http://vitalets.github.io/x-editable/docs.html#select2
It also links to the Select2 documentation and claims that all the Options in Select2 can be set and used as well located here - https://select2.github.io/options.html
I use MockAjax library to simulate an AJAX response in pages like JSFiddle for testing. In my JSFiddle demo here http://jsfiddle.net/jasondavis/Lusbqfhs/ I have 2 MockAjax responses set up....
$.mockjax({
url: '/getTaskTags',
responseTime: 400,
response: function(settings) {
this.responseText = [
{id: 1, text: 'user1'},
{id: 2, text: 'user2'},
{id: 3, text: 'user3'},
{id: 4, text: 'user4'},
{id: 5, text: 'user5'},
{id: 6, text: 'user6'}
];
}
});
$.mockjax({
url: '/getTaskTagById',
responseTime: 400,
response: function(settings) {
this.responseText = [
{id: 1, text: 'user1'},
{id: 2, text: 'user2'},
{id: 3, text: 'user3'},
{id: 4, text: 'user4'},
{id: 5, text: 'user5'},
{id: 6, text: 'user6'}
];
}
});
They both are supposed to return a Mock JSON string for my Selection list to be populated with.
Here is my code for the demo...
$(function(){
//remote source (advanced)
$('#task-tags').editable({
mode: 'inline',
select2: {
width: '192px',
placeholder: 'Select Country',
allowClear: true,
//minimumInputLength: 1,
id: function (item) {
return item.CountryId;
},
// Get list of Tags from AJAX request
ajax: {
url: '/getTaskTags',
type: 'post',
dataType: 'json',
data: function (term, page) {
return { query: term };
},
results: function (data, page) {
return { results: data };
}
},
formatResult: function (item) {
return item.TagName;
},
formatSelection: function (item) {
return item.TagName;
},
initSelection: function (element, callback) {
return $.get('/getTaskTagById', {
query: element.val()
}, function (data) {
callback(data);
});
}
}
});
});
Now in the demo when you click the field to select Tags, it just keeps "loading" and never gets a result. Looking at the Console, it seems my MockAjax request is not working, however the 2nd one is working so I am not sure what is wrong with my AJAX request?
I could really use some help if someone can help to get this to work I would be very greatful, I have spent my whole night without sleep and am not even any closer to a working solution! Please help me!
Thank you
X-Editable uses Select2 3.5.2 which doesn't use jQuery.ajax() directly. It has its own ajax function and calls jQuery.ajax() like that:
transport = options.transport || $.fn.select2.ajaxDefaults.transport
...
handler = transport.call(self, params);
That's why $.mockjax({url: '/getTaskTags'... does not work.
To get it work you need to create your own transport function, something like that:
var transport = function (queryParams) {
return $.ajax(queryParams);
};
and set the transport option:
ajax: {
url: '/getTaskTags',
=> transport: transport,
type: 'post',
dataType: 'json',
data: function (term, page) {
return { query: term };
},
results: function (data, page) {
return { results: data };
}
},
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 };
},