Trying to work out how to use the select2 templating function with a dynamic select2 dropdown to also show the extra data in a JSON response
My question does not relate to how to create the HTML template formating (I have already figured that out). I want to know how to make templating work when loading remote data - at the moment the remote data load function overwrites the templating...
Below is an example of what I mean by "templating" the result. I want to be able to specific the formating for the "otherData" and "extraData" fields
Current example data format (used by the code below that does not work with templating)
{"12":"DASGDSA67"}
Proposed example data (as JSON with extra data)
{"id":"12","value":"DASGDSA67","otherData":"Brunswick","extraData":"Heads"}
View (Javascript)
<script type="text/javascript">
$(document).ready(function() {
$(".company2").select2();
$(".location2").select2({
templateResult: formatState
});
});
$(".company2").select2().on('change', function() {
var $company2 = $('.company2');
$.ajax({
url:"../api/locations/" + $company2.val(),
type:'GET',
success:function(data) {
var $location2 = $(".location2");
$location2.empty();
$.each(data, function(value, key) {
$location2.append($("<option></option>").attr("value", value).text(key));
});
$location2.select2();
}
});
}).trigger('change');
function formatState (state) {
if (!state.id) { return state.text; }
var $state = $(
'<h1>' + state.element.value() + '</h1>' + '<p>' + state.element.otherData() + '</p>'
);
return $state;
};
</script>
Related
I have two select2. The first one fills in automatically and selects the first default value.
My second select2 that shows data depending on the data that the first select2 has, works by AJAX.
My problem is that I want when the value of the first select2 changes, the second select2 is updated and selects the first value from the list of options.
I have seen that in other posts and it has not worked for me. Investigating more on my own I have realized what my problem is.
The second select2 doesn't update the values, fetching them from the database until I click on it.
I would like this second select2 that works by ajax to search for the values automatically when I change the option of the first select2 and to select the first resulting option for me.
I attached the code so you can get an idea
function filtersTable() {
let center_select = $('#center_bookings_today_table');
$.each(centers, function (i, center) {
center_select.append('<option value="' + i + '" title="' + center + '">' + center + '</option>');
});
$('#center_bookings_today_table').select2({
placeholder: '',
});
getGroupsTable();
}
function getGroupsTable() {
let center = $('#center_bookings_today_table').val();
$("#group_bookings_today_table").val('').trigger('change');
let data = '?center=' + center;
$( "#terminals_hours" ).empty();
$('#restrictions').hide();
$("#group_bookings_today_table").select2({
ajax: {
url: '{{ route('get_search_groups_center', ['client' => $client]) }}' + data,
dataType: 'json',
processResults: function (response) {
return {
results: response
};
},
cache: true
},
language: {
inputTooShort: function () {
return '{{ trans('common.insert_chars') }}';
}
}
});
$("#chart_bookings_today_table").hide();
}
Thanks in advance. Excuse my English I'm using google translator
I am in a spot here trying to parse BBCode upon a AJAX success : item.message object. I am using jQuery 1.11. I have tried passing the var result in place of item.message, and only shows the [object] errors. I have tried wrapping item.message with XBBCODE and same thing.
Im not sure what to do, the script is great otherwise. We must parse bbcode to HTML or a method that can be managed PHP-side, but I don't think this is possible over JSON data.
Currently this is my jQuery code:
$(document).ready(function () {
$.ajax({
url: "/ajax/shoutbox.php",
method: "GET",
dataType: 'JSON',
success: function (data) {
var html_to_append = '';
$.each(data, function (i, item) {
// Object array repeated - not working
var result = XBBCODE.process({
text: 'item.message',
removeMisalignedTags: false,
addInLineBreaks: false
});
/*
currentPost = jQuery(this);
postHTML = bbcodeToHTML(currentPost.html());
currentPost.html(postHTML);
*/
html_to_append +=
'<div class="shoutbox-container"><span class="shoutDate">' +
jQuery.timeago(item.date) +
' <span style="color:#b3b3b3">ago</span></span><span class="shoutUser"><img src="' +
item.avatar +
'" class="shout-avatar" /></span><span class="shoutText">' +
item.message +
'</span></div><br>';
});
$("#shoutbox").html(html_to_append);
$(".shoutbox-container").filter(function () {
return $(this).children().length == 3;
}).filter(':odd').addClass('shoutbox_alt');
$(".shoutbox-container").each(function () {
$(this).parent().nextAll().slice(0, this.rowSpan - 1).addClass('shoutbox_alt');
});
}
});
});
As you see, I'm trying to make use of the following javascript:
https://github.com/patorjk/Extendible-BBCode-Parser
I've followed the instructions exactly, before moving into the JS above with no success either way. I get this:
[object][Object]
For each iteration of the message object coming back (its a custom AJAX shoutbox).
Commented, you can see another method I have tried to no success. Any help is appreciated!
Update: Working
Thank you, Quiet Nguyen for the suggestion for replacing item.message with result.html and updating text: object
I was wondering if someone could help me understand how to access data in my json doc.
[
{
"article":"title",
"img_thumb":"images/image.png",
"article_content":"This is content",
"alt":["keyword", "keyword2"]
},
{
//here's article 2
}
]
When document.ready, I'm executing this function, which works perfectly:
var article_populate = function(){
$.getJSON('json/test.json', function(data){
$.each(data, function(key, val){
var article = "<div class='thumb'><img src='" + val.img_thumb + "' class='img_thumb'><div class='div_btn article' id='" + val.article + "'>" + val.article + "</div></div>";
$('#srch_rslt').append(article);
});
})
}
Then if the user clicks on the article title, I want to append the article content from json to the div where the article title is.
Update: this is working now.
$('#srch_rslt').on('click', '.article_title', function(){
var get_article = $(this).attr('id');
console.log(get_article);
$.getJSON('json/test.json', function(data){
$.each(data, function(key, val){
if(val.article_id == get_article){
console.log(val.article_content)
$('#' + get_article).parent().append(val.article_content);
}
});
});
});
It looks like you are using $.getJSON incorrectly in your second example, whereas you are using it correctly in the first. Compare
$.getJSON('json/test.json', function(data, key, val){
versus
$.getJSON('json/test.json', function(data){
$.each(data, function(key, val){
Edit in response to edit of original question:
You will need to do something like this:
$('#srch_rslt').on('click', '.article_title', function(){
var get_article = $(this).attr('id');
console.log(get_article);
var article = $(this);
$.getJSON('json/test.json', function(data){
$.each(data, function(key, val){
if(val.article_id == get_article){
console.log(val.article_content)
article.parent().append(val.article_content);
}
});
});
});
Again, as mentioned in the comments, I recommend reading up on how this works in JavaScript.
You shouldn't use the article.title as an id since it can have illegal characters (',", à, é....).
Since your data structure is an array you can get to the data using the index of the clicked article:
var articleIndex = $(this).index();
with this you can get the corresponding data from your json:
var articleData = data[articleIndex]
Now you can append the article content:
$('selector_where_you_want_data').append(articleData.article_content);
The quick and dirty way is:
$('selector_where_you_want_data').append(data[$(this).index()].article_content);
val is an array with multiple articles right?
so it seems logical that your call gives undefined for val.article
i your json file article is not the lowest level so it should be something like
val.0.article.search(get_article)
val.1.article.search(get_article)
I'd suggest dumping the content of var to console using console.log(var); to see how to access the data correctly or if the data is loaded properly.
I want to send json data from my controller to my view when a specific action happens.
I used this on controller to send the data
[HttpGet]
public JsonResult JSONGetParking(int buildingID){
return this.Json(
new
{
Result = (from obj in db.Parkings.Where(p => p.buildingID == buildingID) select new { ID = obj.ID, Name = obj.note })
}
, JsonRequestBehavior.AllowGet
);
}
it works very good
on my script i used this:
FloorScript.js
$(document).ready(function () {
$('#buildingID').change(function () {
alert("what is not");
$.getJSON('JSONGetParking?buildingID=' + $('#buildingID').val(), function (data) {
alert("afd");
var items = " ";
$.each(data, function (obx, oby) {
items += "<option value='" + oby.ID + "'>" + oby.Name + "</option>";
});
$('#parkingID').html(items);
});
});
});
I have opened google chrome and I can see the request and the response like this:
i can see the two text that i alerted
However, on my selector, i just see undefined value
Html
<div id="editor-label">
<select id="parkingID" name="parkingID"></select>
</div>
I have added the jquery in this
#section scripts {
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/Scripts/FloorScript.js");
}
You're not looping on the correct variable.
You did this:
$.each(data, function (obx, oby) {
whereas you should do this:
$.each(data.Result, function (obx, oby) {
This is pretty visible in the Google Chrome screenshot you provided. As you can see the returned JSON has a property called Result which is the collection whereas you were looping over the data variable which is not an array - it's just a javascript object that has a property called Result which is the array you wanna be looping through.
Also I'd replace:
$.getJSON('JSONGetParking?buildingID=' + $('#buildingID').val(), function (data) {
with:
$.getJSON('JSONGetParking', { buildingID: $('#buildingID').val() }, function (data) {
and of course get rid of this hardcoded url over there and use an url helper to generate it, on the dropdown as an HTML5 data-* attribute:
#Html.DropDownListFor(
x => x.BuildingId,
Model.Buildings,
new {
id = "buildingID",
data_url = Url.Action("JSONGetParking")
}
)
and then inside the change event you can trivially easy retrieve this url and avoid hardcoding it (and of course taking the risk of breaking your code when you deploy it in IIS in a virtual directory or simply change the routing pattern of your application):
$('#buildingID').change(function () {
var url = $(this).data('url');
$.getJSON(url, { buildingID: $('#buildingID').val() }, function (data) {
Alright, now the initial mess is tidied up.
use data.Result in your each loop
$(document).ready(function () {
$('#buildingID').change(function () {
alert("what is not");
$.getJSON('JSONGetParking?buildingID=' + $('#buildingID').val(), function (data) {
alert("afd");
var items = " ";
$.each(data.Result, function (obx, oby) {
items += "<option value='" + oby.ID + "'>" + oby.Name + "</option>";
});
$('#parkingID').html(items);
});
});
});
Hope this helps...
So, the Javascript code which can be found below doesn't seem to be functioning properly.
The goal is to get the text below the map to change on hover of the rooms.
Map Page
The JSON (zadias.me/SVG/rooms.json) data that pulls the data seems to be where I'm faulting, I think. When I test/debug the code by placing .innerHTML statements that would print in the text field, it would work if I placed the .innerHTML before the $.ajax, however, if I put the .innerHTML function in the "success" part of the .ajax, it wouldn't work..
Javascript:
$(document).ready(function(){
var json = (function () { //this function obtains the data
var json = null;
$.ajax({
'async': false,
'global': false,
'url': 'http://zadias.me/SVG/rooms.json',
'dataType': "json",
'success': function (data) {
json = data;
}
});
return json;
})();
function hashTag(){
var hashTag, hash2;
hashTag = location.hash; //obtains the part of the URL with the hash tag and what follows
hashTag = hashTag.replace(/#*/, ''); //replaces the hash tag
if(hashTag.length > 0){
for(i=0 ; i<json.rooms.length ; i++){
if (json.rooms[i].roomId == hashTag) //linear search through array of rooms to see if any equal the hashTag
{
document.getElementById('room_info').innerHTML = '<img src="images/' + json.rooms[i].image + '" /><h4>' + json.rooms[i].name + '</h4>' + json.rooms[i].HTMLdescrip;
} //loads the data from the JSON data.
}
}
};
function setHash(){
window.location.hash = this.id; //creates the hash link based on the object's id (object id acquired from the JSON data) and sets it
};
function setHTML(){
for(i=0 ; i<json.rooms.length ; i++){
if (json.rooms[i].roomId == this.id)
{
document.getElementById('room_info').innerHTML = '<img src="images/' + json.rooms[i].image + '" /><h4>' + json.rooms[i].name + '</h4>' + json.rooms[i].HTMLdescrip;
}
}
};
window.onload = hashTag();
$(".active").click(setHash);
$(".active").mouseenter(setHTML);
//$(".active").mouseover(setHTML);
$(".active").mouseleave(hashTag);
});
I understand that it's a bit localized, how could I change this up?
If I'm getting it right, you need the variable json to be global. Just take off the var at the beginning and see if that helps.
You may want to try something more along these lines:
// this returns a promise
var json,
response = $.ajax({
'async': false,
'global': false,
'url': 'http://zadias.me/SVG/rooms.json',
'dataType': "json",
'success': function (data) {
json = data;
}
});
window.onload = function() {
// ensures that the ajax has returned a value
response.done(hashTag);
};
The document doesn't really have to be ready for you to run an AJAX request.
You may want to take a look here for accessing the SVG elements: How to access SVG elements with Javascript. Requires a change from <embed> to <object>
Here's a version of your code with a few updates:
var json;
$(document).ready(function(){
$.ajax({
'global': false,
'url': 'http://zadias.me/SVG/rooms.json',
'dataType': "json",
'success': function (data) {
json = data;
hashTag();
$(".active")
.click(setHash)
.mouseenter(setHTML)
.mouseleave(hashTag);
}
});
});
function hashTag(){
//get everything in the URL after the #
var hash = location.hash.replace(/#*/, '');
if(hash.length > 0){
//linear search through array of rooms to find the hashTag
$.each( json.rooms, function( room ) {
if (room.roomId == hash) {
$('#room_info').html(
'<img src="images/' + room.image + '" /><h4>' +
room.name + '</h4>' + room.HTMLdescrip
);
} //loads the data from the JSON data.
});
}
};
// creates the hash link based on the object's id
// (object id acquired from the JSON data) and sets it
function setHash(){
window.location.hash = this.id;
}
function setHTML(){
$.each( json.rooms, function( room ) {
if (room.roomId == this.id) {
$('#room_info').html(
'<img src="images/' + room.image + '" /><h4>' +
room.name + '</h4>' + room.HTMLdescrip
);
}
});
}
What I changed:
Made the json variable global.
Removed the async:true. Never use that!
Removed global:false. You don't have any global Ajax event handlers, so this flag has no effect.
Removed unnecessary quotes around the $.ajax() property names.
Removed the event handler setup at the end of the code.
Moved that initialization inside the $.ajax() callback since that is when the data is ready.
Chained together the event handler setup on $(".active") instead of repeating the selector call.
Used $.each() instead of the for loops for simplicity.
Changed the json.rooms[i] references to room thanks to $.each().
Used $('#foo').html(html) instead ofdocument.getElementById()and.innerHTML`, again for simplicity.
Simplified the setup of the hashTag variable and changed its name to hash to avoid confusion with the function name.
Removed unnecessary semicolons at the end of function definitions.
Made the indentation and formatting more consistent.
Shortened the excessive line lengths.
Some of these changes are just stylistic, but they're things I recommend. Naturally you can pick and choose among those after looking through the code.
The important point is making sure that the json data is available not just where it's needed, but when it's needed, and without using async:false.