I was looking at Emberjs recently and found this useful article written by one of its main contributors: Advice on & Instruction in the Use Of Ember.js
It walked me through an example which fetch a list of user data from a server and render them on screen. I'll briefly explain how it worked:
The app contacts the server to fetch a list of user data though ajax
call.
At the end of the ajax call an empty enumerable is returned
immediately, which is later used as a property of a controller.
Once the ajax call is completed, it populates the enum with data which
in turns update the controller's property, and finally triggers an
automatic re-rendering.
This works fine as long as the list is not revisited. As a user revisit the list, say he/she navigates to another state and then comes back, the logic will be triggered again, fetching the data from server and populates the list. However, the list this time is not empty! Thus we have a list of duplicated data. I would like to resolve this by clearing the content of the list when the ajax call is successful. Below is the code for the ajax call:
allAwesomebergs: [],
fetch: function(){
$.ajax({
url: 'https://api.github.com/repos/emberjs/ember.js/contributors',
dataType: 'jsonp',
context: this,
success: function(response) {
response.data.forEach(function(awesomeberg){
this.allAwesomebergs.addObject(App.Awesomeberg.create(awesomeberg))
}, this);
}
});
return this.allAwesomebergs;
},
The above code does not clear the content of the list. I tried adding a line "allAwesomebergs = []" at the beginning of the success function, but what I got was just a blank screen. I thought I may not be doing this correctly, but I looked at the document from Ember and didn't see anything about clearing the content of an Enumerable.
Thus the question is: what is the easiest way to resolve this duplicate loading issue? Clearing the content before hand seems the most obvious but I can't make it work.
You can call clear() before you start adding the new objects. See this documentation.
New code would be:
allAwesomebergs: [],
fetch: function(){
$.ajax({
url: 'https://api.github.com/repos/emberjs/ember.js/contributors',
dataType: 'jsonp',
context: this,
success: function(response) {
this.allAwesomebergs.clear();
response.data.forEach(function(awesomeberg){
this.allAwesomebergs.addObject(App.Awesomeberg.create(awesomeberg))
}, this);
}
});
return this.allAwesomebergs;
},
I think your approach was ok, but it should have been:
this.allAwesomebergs = []
It is all about the this in front of it. So clear is not needed here.
Related
I'm fairly new to using WordPress AND AJAX for that matter. I need to have a Table in my admin area which is populated with enquiries to my site.
I have set up a custom table in the admin panel which is populated by an external database. This works fine. Once this has been populated I want to be able to change a select box to keep track of the status of certain enquiries.
I have inserted the select boxes and all seems well. At this point however, I want to use AJAX to post the changed state (in particular the index no. of the new selected option) back to my database to be populated.
I have found a number of examples to do with this and have spent a wee while trying to get my head around it but once the AJAX post is sent, I am not sure how OR where to deal with the receipt of this and have it update the database.
At the moment the url which the AJAX post points towards is the .php file in which my custom table is stored.
Could someone please explain what each aspect of the following code does, and what steps I seem to missing:
jQuery(function( $ ) {
$(".select-status").on( 'change', function() {
var $currentSelect = $(this);
var currentId = $currentSelect.attr('id');
var url = "/wp-content/plugins/custom-list-table-example/list-table-example.php"; // the script where you handle the form input.
console.log(currentId['value']);
$.ajax({
type: 'POST',
url: url,
data: $currentSelect.serialize(),
success: function(data) {
alert(data);
},
error: function() {
alert('There was an error: Failed to update database');
}
})
});
});
Where select-status is the class given to each select box.
Any help would be massively appreciated.
This site gave me hope but I can't see if this is relevant or where I would implement the different parts within WordPress.
I'm using backbone and nodejs for a single page webapp.
I got a view, which has a model(a blog post) in it. when user click on 'like' button, the view will start ajax send the user'id to server to let the like number +1.
it looks like this:
this.model.save({
likedBy: userModel.get('_id')
}, {
url: '/posts/' + this.model.get('_id') + '/like',
success: function() {
// do something
},
patch: true
});
my problem is, when this code got run. browser start http request to retrieve all the images on the screen, and re-render them. so the screen got a "shake" after user clicked the like button.
this is not happening everywhere, but what caused this? how to stop the "shake"?
thanks for any advance.
When you call this.model.save() the model will update his data in the server and will call your view's render function. The render method will create a new DOM element and replace the old DOM element, that's what causing the flickering (it requests the images again).
I assume you have an API call for Like action (if not it's better to have one) so you can make a sperate AJAX call for like action on your model by adding a function like so:
addLike : function(data) {
Backbone.ajax({
url: '/api/like/'+ this.get('id'),
method: 'POST',
data: data,
success: options.success,
error: options.error
});
}
I've got a pretty strong understanding of php, html & css but i've only just started to dive into javascript & jQuery.
The problem i'm facing is that I have a form on a page that I want first to validate, then when it passes validation to submit 2 ajax requests; the first to insert data into a table in my database and the second to run a query on another table and return the result.
I've got the latter working just fine using the submitHandler method to send the ajax request and update a div on my page with it's result. When I added a second ajax call after or before this one it seems to break...
My question is should there be a problem with having 2 ajax calls in the submitHandler, like below, and if so what would be the correct way to go about this, or even a better way?
$("#contactform").validate({
rules: ...
submitHandler: function() {
// First to insert the contact details using input#firstname etc.
var firstname = $("#firstname").value();
var lastname = $("#lastname").value();
var contactString = 'firstname='+ firstname + '&lastname=' + lastname;
$.ajax({
type: "POST",
url: "insertcontact.php",
data: quoteString,
success: function(server_response){
$('#yourquote').html(server_response).show();
}
});
// Second use width & height submitted from previous page for processquote.php
var width = <?php echo json_encode($cleanpost['width']); ?>;
var height = <?php echo json_encode($cleanpost['height']); ?>;
var quoteString = 'width='+ width + '&height=' + height;
$.ajax({
type: "POST",
url: "processquote.php",
data: quoteString,
success: function(server_response){
$('#yourquote').html(server_response).show();
}
});
}
});
I'm using the 'jquery.validate.js' validation plugin. Again my goal is such that once someone has entered valid details on my form, using Ajax their contact data is inserted into the database then the database is queried using fields submitted on the previous page to retrieve a numerical result to display on the page, without a refresh.
Any pointers you could give me would be much appreciated!
Rob
EDIT: Learning Javascript & Jquery simultaneously isn't such a good idea it seems, i've confused: this.value = ''; with $(this).val(''); as shown in the first 2 variable declarations, this is what was causing problems! Thanks for your useful help anyway guys, will upboat for your assistance.
In your first .ajax() call, you are trying to pass it a value in the data: parameter that you have not created yet. I believe you are wanting to send it the contactString instead.
Unless your two queries depend on each other being done sequentially then you should be able to execute them both asynchronously (essentially at the same moment). If you want the second AJAX call to happen after the first one, you could always pass all of your data parameters to insertcontact.php and once the insertion is done, execute processquote.php with the values you already passed through.
Lastly, I wonder if you are meaning to do this, but both of your AJAX calls overwrite whatever is in the #yourquote DOM element and show it. You might want to provide a separate element to put the response in for each of your two requests. Perhaps #yourquoteinserted and #yourquoteprocessed?
Edit: BigRob, from your comment it sounds as if you want to make synchronous AJAX queries, check out the async property of your .ajax() call. This is from the .ajax() documentation:
async Boolean
Default: true
By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
(emphasis mine)
However, I could be wrong about this but you might actually be able to call one asynchronous AJAX method from within the success function of another. If it starts looking too intermingled for you, you might want to extract the inner call into a function. Rough approximation of what it might look like:
$.ajax({url, data:contactString,
success: function(server_response) {
extractedId = server_response; // you can return data many ways
$.ajax({url2, data:quoteString+"&extra="+extractedId,...
});
}
});
If you perform a synchronous call by setting async:false in the first AJAX call, then you could just store the result into an external (to the AJAX call) variable (or if that doesn't work store it in some DOM element temporarily). Then the javascript will pause execution and won't fire your second AJAX call until the first one has returned.
This is all hypothetical for now, though, and just based off of my understanding of how it should work.
This is a mock of what I'm doing:
function loadPage(pn) {
$('#'+pn).live('pagecreate',function(event, ui){
$('#'+pn+'-submit').click( function() {
$.mobile.changePage({
url: 'page.php?parm=value',
type: 'post',
data: $('form#'+pn+'_form')
},'slide',false,false);
loadAjaxPages(pn);
});
});
function loadAjaxPages(page) {
// this returns the page I want, all is working
$.ajax({
url: 'page.php?parm=value',
type: 'POST',
error : function (){ document.title='error'; },
success: function (data) {
$('#display_'+page+'_page').html(data); // removed .page(), causing page to transition, but if I use .page() I can see the desired listview
}
});
}
in the ajax call return if I add the .page() (which worked in the past but I had it out side of the page function, changing the logic on how I load pages to save on loading times), make the page transition to the next page but I can see the listview is styled the way I want:
$('#display_'+page+'_page').html(data).page();
Removing .page() fixes the transition error but now the page does not style. I have tried listview('refresh') and even listview('refresh',true) but no luck.
Any thoughts on how I can get the listview to refresh?
Solution:
$.ajax({
url: 'page.php?parm=value',
type: 'POST',
error : function (){ document.title='error'; },
success: function (data) {
$('#display_'+page+'_page').html(data);
$("div#name ul").listview(); // add div wrapper w/ name attr to use the refresh
}
});
Be sure to call .listview on the ul element
If it didn't style earlier, you just call .listview(), bot the refresh function. If your firebug setup is correct, you should have seen an error message telling you that.
I didn't have time to get down to creating some code before you posted your fix, but here's a little recommendation from me:
if(data !== null){ $('#display_'+page+'_page').html(data).find("ul").listview() }
This is a bit nicer than a new global selector. Also - you don't need the div and you can provide a detailed selector if you have multiple ULs.
caution: the above code requires data !== null. If it's null - it will throw an error.
If you add items to a listview, you'll need to call the refresh() method on it to update the styles and create any nested lists that are added. For example:
$('#mylist').listview('refresh');
Note that the refresh() method only affects new nodes appended to a list. This is done for performance reasons. Any list items already enhanced will be ignored by the refresh process. This means that if you change the contents or attributes on an already enhanced list item, these won't be reflected. If you want a list item to be updated, replace it with fresh markup before calling refresh.
more info here.
I'm having a problem with, guess what, IE8. The following code, simplified for clarity, does not work at all:
alert('before get');
$.get(getActivityURL('ActionName',{
ts: new Date().getTime(), ...other params...}),
{cache:false;},
function (xml) {
alert("in get callback");
},'xml'); // End $.get()
alert('in after get');
The getActivityUrl() outputs a valid URL with request parameters.
This works correctly in FF and Chrome. However, in IE8, this doesn't even get into the $.get() callback. I get the "before" and "after" alerts, but not the "in" alert and indeed, nothing happens and the request is NOT sent. I don't really know what to think here.
The response headers are "Content-Type:application/xml; charset:iso-8859-1" as confirmed in FF.
EDIT: $.post() doesn't work, either.
IE is infamous for caching. So you need to make sure you are not getting a cached result.
You can disable caching globally by setting the cache property value to false in the ajaxStart method.
$.ajaxSetup({
cache: false
});
Or If you want to eliminate the cached result in a specific ajax call, Append a unique number to the end of the url. You may use the $.now() method to get a unique number
$.get("someurl.php?" + $.now() ,function(result) {
// do something with result
});
$.now() method return a number representing the current time.
I'm not sure if it is a problem but try to remove ";" in {cache:false}
IE doesn't like any additional stuff in {}, eg
{a:a,b:b,c:c,} will work in FF but not in IE
I think so there is Cache problem in IE.
So add Math.random(), one more parameter at the end like "&mathRandom="+Math.random();
Because IE will recognise same request as previous one so it will give data from cache instead of firing request.
$J.get(getActivityURL('ActionName'
// End $.get()
Is this correct? I mean $J... Are you using more than one JS framework or something?
have u tried:
$.ajax({
url: getActivityURL('ActionName',{ts: new Date().getTime(), ...other params...}),
data: data,
success: function (xml) {
alert("in get callback");
},
dataType: 'xml'
});
Just a guess
EDIT:
I found a interesting thread that might help you, check this out:
jQuery issue in Internet Explorer 8