How to preselect Select2.js on page load using API call? - javascript

I have the following code:
var zoneListEl = $("#zones-list"),
zoneListPopupEl = $("#zones-list-popup");
$.ajax({
type: 'GET',
url: 'https://my-domain.com/api/v1/zone/get-zone-by-ip'
}).then(function (data) {
var zone = data.data.zones,
option = new Option(zone.name + ", " + zone.abbreviated_state_name, zone.id, true, true);
zoneListEl.append(option).trigger('change');
// zoneListPopupEl.append(option).trigger('change');
});
The code above works well. I mean, on the page load that ajax call happens and puts the response as an option inside the $("#zones-list") (which is a select element) as a default value.
My problem is, I have two different select elements that I want to do the same for both. When I uncomment the following line
zoneListPopupEl.append(option).trigger('change');
Then the code doesn't work (without throwing error) and I cannot see any default value (<option>) for neither selects. Why? Why when I do that for one select it works well but for two selects, it doesn't?
Update: I set that line inside setInterval like this:
setInterval(function(){ zoneListPopupEl.append(option).trigger('change'); },3000);
In this case, the default value (option) will be shown for zoneListEl on page load and after 3 sec it does away.

Related

Storing and updating a global value in the success function across multiple Ajax POST calls

I have two HTML elements: 1). the div element is a multiple select (it is a predefined widget that automatically creates the multiple select element) and 2). a button that triggers onclick event.
On the JS side, there is the global variable 'prev_selection' which is set to empty array for now. The idea of prev_selection is to remember the array of values in the multiple select div element before user clicks the button. I want to remember the value before and after a click to see what selections have been added/removed.
When the button is clicked, 'sendData()' is called. It gets the selected data from the div element. Then, it performs some operations using the prev_selection to know what the newly selected values are (in the beginning everything is newly selected in the div).
I want to find out the additions/deletions in the selected values between user clicks. For that, I update the prev_selection with 'selected_data' that I get from the div element jut after the click.
But this does not work as expected. There is something happening with the asynchronous Ajax call and I am not able to find a better solution for this. Everytime a click happens you had expect that 'prev_selection' remembers the value before the click but instead when I print it using console.log() (as shown in the code) it already gets updated to the latest selections even before reaching the success function (where it is supposed to get updated).
Thanks in advance! And please let me know if further explanation is required.
<!-- multiple select/deselect div -->
<div id="someSelectionID"></div>
<button id="updateButtonID" onclick="sendData()">Click to send</button>
// at first, no data is selected
var prev_selection = [];
function sendData() {
// get the selected data from the div element "someSelectionID"
let selected_data = $('#someSelectionID').val();
// perform some operations on the selected data
// this operation involves the use of prev_selection
// printing prev_selection already has value of updated click
console.log(prev_selection );
$.ajax({
type: "POST",
url: "<some url>",
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: JSON.stringify( < some data > ),
success: function(result) {
console.log(result);
/* once the request is successfully done update the
previous selection to what the current selected data is */
prev_selection = selected_data;
}
});
}
Try this
$.ajax({
type: "POST",
url: "<some url>",
dataType: 'json',
contentType: 'application/json;charset=UTF-8',
data: JSON.stringify( < some data > ),
}
}).then(function(response){
if (response.status === 200){
console.log('succeed');
} else {
console.log('failed')
}
});
So it worked by changing this line
prev_selection = selected_data;
to:
prev_selection = Array.from(selected_data);
Because the prev_selection variable kept changing without me updating, it lead me to believe that it was some kind of reference to value instead of value itself. So just using Array.from to do a shallow copy actually worked.

Complete function of AJAX request not behaving as expected

I am working on a jquery/ajax project. On document ready, I have the following code:
$(document).ready(function () {
$.ajax({
url: '/Main/ReturnGroups/',
dataType: "json",
success: function (data) {
$('.column').each(function (index) {
let indexVar = index;
let colID = $(this).attr("id");
for (let i = 0; i < data.length; i++) {
if ($(this).attr("id") == data[i].ColumnID) {
let thisID = $(this).attr("id");
let thisGroupID = data[i].ID;
$.ajax({
url: '/Main/GetFullGroup/',
data: { groupID: thisGroupID },
success: function (html) {
$('#' + thisID).append(html); //this html inserts a portlet (JqueryUI) based element
}
});
}
}
})
},
complete: function () {
alert($('.portlet').length); //returns 0 (leads me to believe its being run before success function
AddPageProperties(); //this function is supposed to add a bunch of classes to the elements injected in the success function but doesnt actually add the classes when its here
}
});
})
It seems to me that the contents of the complete: function is running asynchronously with the success function. From my understanding the purpose of the complete function is to run once the ajax success (or error) function is completely done.
The code is iterating all the columns and returning all the groups which have the same column id in my database, then passing the groupID to another webmethod which is then querying for all tasks and using the passed in groupID only pulling the tasks that are associated to the group, then using that data to inject a partial view to place the tasks/groups in their respective locations.
Things I've tried:
-Put the AddPageProperties() function in a button click, and after the ajax is finished, click the button. This works exactly as intended.
-use ajaxStop(). While this does work as I want for document ready, once I submit another ajax request it runs the function again, thus duplicating the code. My project uses ajax requests when elements are moved around the screen so this doesnt work.
-Try and get the details of an element to see if the html is even there in the first place when the complete: function() is run. The alert in the code snippet returns 0, which leads me to believe the HTML is not there when that alert is executed.
-using the index of the each function to determine the end of the iteration and then run the function, but again does not apply classes in the function. I tried to again do an alert to see if the elements are present, but they are not.
-set async to false, but the browser just says that its deprecated and it doesnt change any behavior
Any advice on the path towards a solution is appreciated. My goal is once all the HTML is injected, then and only then run this function and never again until page is reloaded sometime later.
I would like to stick with JQuery/ajax as my project is dependent on JQuery for Bootstrap.

Jquery dependent dropdown only works with excessive variables

I have very basic JS skills, so please excuse me if I'm trying to fix something what doesn't need fixing.
I use select2 dropdown. When user selects any option, it gets posted to remote file, which returns possible options (in JSON format) to be displayed in 2nd (dependent) dropdown.
1st select looks following:
<select name="restaurant_id" id="restaurant_id">my_options_go_here</select>
2nd (dependent) select looks:
<select name="division_ids_array[]" id="division_ids_array" multiple="multiple"></select>
And here's JS code:
$(function () {
function ajax_post_data_get_divisions(parameters) {
$.ajax({
method: "POST",
url: "ajax.php",
cache: false,
data: parameters,
success: function(data) {
var dropdown_options=$('#division_ids_array');
dropdown_options.empty();
var dropdown_options="";
$.each(data, function(key, val) {
dropdown_options+='<option value="'+val.division_id+'" '+val.selected+'>'+val.division_name+'</option>';
});
$(dropdown_options).appendTo("#division_ids_array");
}
});
}
$('#restaurant_id').on("change", function(e) {
parameters=$("#my_form_id").serialize();
ajax_post_data_get_divisions(parameters);
});
});
Everything works fine, but I somehow believe these lines are excessive:
var dropdown_options=$('#division_ids_array');
dropdown_options.empty();
var dropdown_options="";
Please excuse my ignorance, but it looks variable dropdown_options gets created first, then it gets set to empty, and then the same variable is created again?
Unfortunately, if I remove at least one line, nothing works. For example, if I try to simply code to:
var dropdown_options=$('#division_ids_array');
dropdown_options.empty();
dependent dropdown remains empty. Is it an error in my code?

Ajax variable reuse buildup

On getData() I use an ajax get request to pull a few li and append them to the container. On the success of the ajax call I make a variable called next_load which gets the data-attribute and passes it as the url for the next get data call. The problem I have is that on the second click there is a build up of variable on the call. In the console I can see the first date being passed with the second date as well. The goal is on page load to get the first dates. Then clicking on the box to get the next dates and so on.
HTML:
<div id = "calendar">
<div class = "box">
<ul class = "label">
<li>Sun</li>
<li>Mon</li>
<li>Tue</li>
<li>Wed</li>
<li>Thur</li>
<li>Fri</li>
<li>Sat</li>
</ul>
</div>
<ul class = "box-content">
</ul>
</div>
in console:
2 calendar.js:34 2016-03-05 -> on the first get, then this and the next on the second get and it keeps building up.
calendar.js:34 2016-04-09
function getData(url) {
var next_load = '';
$.ajax({
url: 'student/calendar/' + url,
type: 'GET',
success: function(response) {
var $result = $(response).filter('li');
$('.box-content').append($result);
next_load = $result.last().attr('data-date');
useNextLoad(next_load); // dont use the value till the ajax promise resolves here
}
})
}
getData('show/2016/02');
function useNextLoad(next_load){
var load = next_load;
$('.box').click(function(){
getData('load/' + load);
console.log(load); // when i pass the next_load Im getting the previous next load and the new next load at the same time. Then on the next click the amount compounds.
});
}
If I reset the variable next_load would that keep the build up from occuring? I tried to empty the variable before the ajax call but I still get the build up.
Might be an issue with the click function being multiply applied to .box. You may want to remove any existing click handler from .box before binding a new one. See How to remove all Click event handlers in Jquery
function useNextLoad(next_load){
var load = next_load;
$('.box').off("click"); // Remove any click handlers already on .box
$('.box').click(function(){
...
Of course, you can also chain your calls in jQuery if you want to be more compact.

How do I trigger events after event handlers are bound in ajax calls when the page loads?

Problem:
I've got 2 drop downs, both populated by information from a database and dependent on some initial information (a json array created in php). The second drop down is also dependent on what was selected in the first dropdown. Once the second dropdown has been selected, the users selections are saved in another database table. If the user leaves and then comes back, I want to be able to reset the drop downs to what they previously selected (but still let them change their selections).
Context:
I have some code that looks like the following:
function eventHandler2(event) {
$.ajax({
url: "someotherurl.php",
data: event.data["context"],
success: function(data) {
// Do some stuff
}
});
}
function eventHandler1(event) {
event.data["context"][$(event.target).id()] = $(event.target).val();
$.ajax({
url: "someurl.php",
data: event.data["context"],
success: function(data) {
$("#element").append(build_input("input2", data));
$("#element input2").change({"context": event.data["context"]}, eventHandler2);
}
});
}
$(document).ready(function() {
var context = // php generated json array.
$("#element").append(build_input("input1", context));
$("#element input1").change({"context": context}, eventHandler1);
});
context includes some data that has to be initialized outside of the event handler and is added to durring events, and build_input just returns an html string of a form input element built with options determined by data or someData. At times the entire html element that includes eventHandler1 (and eventHandler2) will be removed and reinitialized.
My issue is that I want to initialize the two form inputs (built using build_input) with some default values pulled from a database, but once those values have been set I don't want any reinitialization or event handling to use those initial values (which makes adding them to the context object difficult since that object will be used when binding the event handlers).
I would like to set the value for the inputs and then call a change event to simulate a user selecting those values, but because the input elements are built using ajax data, those change events are being getting called before the ajax request have returned and built the input elements.
I could solve this with timeouts, but because the the javascript might run slower on different machines and the ajax calls could take longer than normal, I don't plan on doing it that way. Still, ideally I would like something like this:
$("#element .input1 option[value='" + initial_value + "']").attr('selected', true);
$("#element .input1").change();
to be called when the page loads but only after the elements have been built and bound.
Question:
Is there any way to trigger change events (simulating the user selecting options) only when the page is first loaded and only after the ajax request to build the html input elements have returned?
Is there any way to trigger change events (simulating the user selecting options) only when the
page is first loaded
and only
after the ajax request
to build the html input elements have returned?
These are two separate events. If you need to ensure both events have ocurred use <body onload="loadedBody=true"> and take advantage of the success: attribute of the $.ajax function like this:
function eventHandler1(event) {
event.data["context"][$(event.target).id()] = $(event.target).val();
$.ajax({
url: "someurl.php",
data: event.data["context"],
success: function(data) {
$("#element").append(build_input("input2", data));
$("#element input2").change({"context": event.data["context"]}, eventHandler2);
ajaxComplete();
}
});
}
var ajaxCompleted;
function ajaxComplete() {
if((loadedBody == true) && (ajaxCompleted == false)) {
$("#element .input1 option[value='" + initial_value + "']").attr('selected', true);
$("#element .input1").change();
} else {
setTimeout('ajaxComplete()', 100);
}
}
Don't worry about the setTimeout. It will rarely be used because the page will likely have loaded before the AJAX result arrives.

Categories

Resources