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.
Related
I have a question regarding ajax array. I have create two arrays in a javascript file like below.
$(document).ready(function () {
categoryarray = [];
productarray = [];
Then if I want to refer to these arrays from another javascript file with the script inside html follows the script of the javascript file that creates two arrays, but it doesn't show anything, not even console reporting error.
Below is how I refered the array in another javascript file, it didn't work.
$(document).ready(function () {
$.ajax({
type: 'GET',
url: 'my_script.js',
success: function(data) {
for(var k=0;k<categoryarray.length;k++){
if(categoryarray[k][0]!==""){
$('.tree').append('<li id="Cate_' + k + '">'+categoryarray[k][1]+'</li>');
for(var l=0;l<productarray.length;l++){
if(categoryarray[k][0]==productarray[l][2]){
$('#Cate_' + k).append('<ul id="Pro_' + l + '"></ul>');
$('#Pro_' + l).append("<li>"+productarray[l][1]+"</li>");
}
}
}
}
},
error: function() {
$('.tree').text('Failed to load the data');
console.log('Error');
}
});
});
Can anyone tell me what I have done wrong and how to fix them? Many thanks!!!
First of all place your code inside a function that you will call on some event. If you want to process your arrays after AJAX call then call that function after AJAX success. Browser render HTML from top to bottom so your script in HTML will run as soon as browser bump into script. On the other hand jQuery on ready will wait until all of the page content is fully loaded (all images, assets etc) - whole DOM, so your arrays will stay undefined.
You can fix it either by moving that code from HTML to jQuery ready function or by moving array declarations in HTML.
Anyway, if that script from HTML should run when document is ready, then it is more reasonable to move javascript code from HTML to jQuery ready function.
I am creating a SPA in DurandalJS with MVC, and have jQuery loading a <select> with options loaded from a database. Setting breakpoints i was able to follow the stack all the way down the chain and verify that all of my ajax loading and jQuery calls were occuring, but when I go to check the select box, it is empty, including the inner html of the tag and the dropdown elements themselves.
What's weird though is that the items will load if I navigate to another page and then come back to the original page (since this is an ajax-ified single page application it doesn't actually navigate in the traditional sense.
Why is this happening and how can I fix it?
Code to load the data:
function addProjectSelectorOptions(projects) {
$('#project-picker').empty();
for (var i = 0; i < projects.length; i++) {
console.log(projects[i]);
$('#project-picker').append(new Option(projects[i]["Name"], projects[i]["Id"]));
}
}
function loadData() {
$.ajax({
url: '/ClubhouseData/GetProjects',
type: 'GET',
cache: false,
success: function (results) {
console.log(results);
addProjectSelectorOptions(results);
}
});
};
loadData();
Solved:
I wrapped loadData() in a jQuery onDocumentLoad call and it fixed the problem.
I'm not sure if this will actually be possible, since load() is an asynchronous method, but I need some way to basically Load several little bits of pages, one at a time, get some data included in them via JavaScript, and then send that over via Ajax so I can put it on a database I made.
Basically I get this from my page, where all the links I'll be having to iterate through are located:
var digiList = $('.2u');
var link;
for(var i=0;i<digiList.length;i++){
link = "http://www.digimon-heroes.com" + $(digiList).eq(i).find('map').children().attr('href');
So far so good.
Now, I'm going to have to load each link (only a specific div of the full page, not the whole thing) into a div I have somewhere around my page, so that I can get some data via JQuery:
var contentURI= link + ' div.row:nth-child(2)';
$('#single').load('grabber.php?url='+ contentURI,function(){
///////////// And I do a bunch of JQuery stuff here, and save stuff into an object
///////////// Aaaand then I call up an ajax request.
$.ajax({
url: 'insertDigi.php',
type: 'POST',
data: {digimon: JSON.stringify(digimon)},
dataType: 'json',
success: function(msg){
console.log(msg);
}
////////This calls up a script that handles everything and makes an insert into my database.
}); //END ajax
}); //END load callback Function
} //END 'for' Statement.
alert('Inserted!');
Naturally, as would be expected, the loading takes too long, and the rest of the for statement just keeps going through, not really caring about letting the load finish up it's business, since the load is asynchronous. The alert('Inserted!'); is called before I even get the chance to load the very first page. This, in turn, means that I only get to load the stuff into my div before I can even treat it's information and send it over to my script.
So my question is: Is there some creative way to do this in such a manner that I could iterate through multiple links, load them, do my business with them, and be done with it? And if not, is there a synchronous alternative to load, that could produce roughly the same effect? I know that it would probably block up my page completely, but I'd be fine with it, since the page does not require any input from me.
Hopefully I explained everything with the necessary detail, and hopefully you guys can help me out with this. Thanks!
You probably want a recursive function, that waits for one iteration, before going to the next iteration etc.
(function recursive(i) {
var digiList = $('.2u');
var link = digiList.eq(i).find('map').children().attr('href') + ' div.row:nth-child(2)';
$.ajax({
url: 'grabber.php',
data: {
url: link
}
}).done(function(data) {
// do stuff with "data"
$.ajax({
url: 'insertDigi.php',
type: 'POST',
data: {
digimon: digimon
},
dataType: 'json'
}).done(function(msg) {
console.log(msg);
if (i < digiList.length) {
recursive(++i); // do the next one ... when this is one is done
}
});
});
})(0);
Just in case you want them to run together you can use closure to preserve each number in the loop
for (var i = 0; i < digiList.length; i++) {
(function(num) { < // num here as the argument is actually i
var link = "http://www.digimon-heroes.com" + $(digiList).eq(num).find('map').children().attr('href');
var contentURI= link + ' div.row:nth-child(2)';
$('#single').load('grabber.php?url=' + contentURI, function() {
///////////// And I do a bunch of JQuery stuff here, and save stuff into an object
///////////// Aaaand then I call up an ajax request.
$.ajax({
url: 'insertDigi.php',
type: 'POST',
data: {
digimon: JSON.stringify(digimon)
},
dataType: 'json',
success: function(msg) {
console.log(msg);
}
////////This calls up a script that handles everything and makes an insert into my database.
}); //END ajax
}); //END load callback Function
})(i);// <-- pass in the number from the loop
}
You can always use synchronous ajax, but there's no good reason for it.
If you know the number of documents you need to download (you can count them or just hardcode if it's constant), you could run some callback function on success and if everything is done, then proceed with logic that need all documents.
To make it even better you could just trigger an event (on document or any other object) when everything is downloaded (e.x. "downloads_done") and listen on this even to make what you need to make.
But all above is for case you need to do something when all is done. However I'm not sure if I understood your question correctly (just read this again).
If you want to download something -> do something with data -> download another thing -> do something again...
Then you can also use javascript waterfall (library or build your own) to make it simple and easy to use. On waterfall you define what should happen when async function is done, one by one.
I have a VIEW, which contains a dataTable and jquery code which enables the dataTable rows to be clickable so that the user can click on a row and an ajax call is made to the server to fetch the detail of that row.
I've manage to make the dataTable row clickable, and called the Ajax function which under debug mode, I can see the POST method is being called. However, the Partial View which the returned by the POST method does not show up on my browser, even though I can see that my code is being called every step in debug mode..
My ajax/jquery is this (ive got this in a VIEW)
<script type="text/javascript">
$(function () {
$('#dTable tbody tr').on('hover', function () {
$(this).toggleClass('clickable');
}).on('click', function () {
var self = this;
$.ajax(
{
type: "POST",
url: "/TR/AllTHeaderTR",
data: { tID: $.trim($(this).find('td:first').text()) },
success: function (data) {
$('#dtable').html(data);
$(self).off('click');
}
});
});
</script>
I can see that when clicked, the code does move through the POST method, /TR/AllTHeaderTR, which ends up doing a : return PartialView("_AllTDetailTR", travlist);
Ive also tried to replace the above with just a normal HTML page with hard coded text, but the page does not render.
Im not clued up on jquery or ajax, so could someone please assist.
Thanks
Naren
Im new to .ajax and so far so good. But I've run into an issue of, I want to run a function once I've used up all the data.
For example I have the following, i run it on 'click':
$.ajax({
url: "url.modal.tothegoods" + (nextPage),
success: function (data) {
//keeps appending data on click
},
error: function () {
alert('balls');
}
})
I've tried the ajaxcomplete function but it runs everytime i load data onto the screen.
It runs everytime i appened data .ajaxcomplete runs. I guess the questions is, how do I run a function once I have no more data to consume. So I am truly done
any tips/tricks would be greatly appreciated
The response depends on which is currently the behaviour of your server part.
If you have hand on it, the most simple solution is that it returns nothing when there is no more data to send. So you may do something as simple as this:
$.ajax({
url: "url.modal.tothegoods" + (nextPage),
success: function (data) {
if (!!data) {
//keeps appending data on click
}
},
error: function () {
alert('balls');
}
})