I'm learning Rails and I understand how ajax call works. But I have a problem: I don't know how can I bind an ajax function on object loaded in the DOM with another ajax function.
In my demo page I use Plupload plugin to upload some files: when the script finish to upload the files I load, with ajax, the thumbnails in my preview window. Everything works fine.
$("#multi_upload").pluploadQueue().bind('UploadComplete', function(up, files) {
$.ajax({
type: "GET",
dataType: 'html',
url: $('.wmk_grid#large_grid').data('gallery-url'),
success: function(result) {
$('.wmk_grid#large_grid').html(result);
}
});
});
$('.plupload_header').remove();
}
Every thumbnail has also a "delete" button: on this button I attach a rails ajax call to delete the single picture.
My coffeescript is this:
$ ->
$('.img_action_remove').bind 'ajax:success', (event, data, status, xhr) ->
$(this).closest('li').remove()
I know the issue: when I load my page I don't have any item with .img_action_remove class: i create them when I upload the pictures with plupload.
How can I fix the second ajax call?
Update: fixed with this script:
$(document).on "ajax:success", ".img_action_remove", (e) ->
$(e.currentTarget).closest("li").remove()
JQuery Delegation
When I load my page I don't have any item with .img_action_remove
class: i create them when I upload the pictures with plupload
$('document').on 'ajax:success', '.img_action_remove', (event, data, status, xhr) ->
$(this).closest('li').remove()
This binds the event to the document & delegates to the class. Means that you can create the class any time you want, and JS should always capture the event
Related
Using dustjs for templating engine within Expressjs 4. Want to render the template client-side when user fills out a form and clicks a search button using xhr. Everything seems to go fine so far as getting the json from xhr call but dust.render does not render the result.
Here is the dust template on the page:
<script id="result-template">
// extra table tags removed for brevity
{#search_results}
{fname}
{lname}
{accountId}
{email}
{status}
{/search_results}
</script>
<div id="output">
Below is the js/jquery in an external js file making the xhr call to server-side. Inside the success callback is where I'm trying to render the result from the call, basically user fills-in a search form and clicks submit:
$(document).ready(function () {
$('#main').on('click', '#search-btn', function (e) {
e.preventDefault();
$.ajax({
url: '/support/search/ah',
type: "post",
headers: {token: sessionStorage.getItem('somekey')},
data: {'phone': $('#mobile').val(),
'email': $('#email').val(),
'fname': $('#fname').val(),
'lname': $('#lname').val()
},
success: function (data, textStatus, request) {
var source = $("#result-template").html();
var compiled = dust.compile(source, "intro");
dust.loadSource(compiled);
dust.render("intro", data, function(err, out) {
$("#output").html(out);
$('#search-result').dataTable();
});
},
error: function (data, textStatus, request) {
// handle error
})
})
xhr call is successful, and I can see that 'data' variable contains the json with values, however, I'm not able to render them using dust.render and there are no js errors being observed when the page loads or when the results come back.
Here is the json result from xhr call:
{"search_results":[{"fname":"Duke", "lname":"Wellington","accountId":"007","email":"duke_wellington","status":"Breathing"}]};
I tried the same template with same json results at atakdubya.github.io replacing its array example and it works fine.
If anyone can point out what I'm doing wrong it would be immensely appreciated.
Depending on your browser, you can't have a script tag with no type or it will be interpreted as Javascript, and Dust isn't valid Javascript.
Try adding type="text/dust" to your script tag. This JSFiddle works for me.
http://jsfiddle.net/Lutr4h2e/1/
I am trying to post a form from one rails app to another hosted on different domains and including files.
I attempted:
$(document).on("click", ".application-form .submission input", function(e){
e.preventDefault();
var form = $(".application-form form");
var data = new FormData(form);
var url = "http://example.com/action";
$.ajax({
url: url,
type: 'POST',
success: function(){
alert('success');
},
error: function(){
alert('error');
},
data: data,
cache: false,
contentType: false,
processData: false
});
});
But the remote server doesn't receive any data, params merely contains the controller name and action.
I also have tried using remotipart and setting up my form with form_for(#application, url: "http://example.com/action", html: {multipart: true}, remote: true) and if I include a file, the server receives [object Object] instead of correct param names and values. If I do not include a file, then the params are sent and received correctly, but I need to include files with the upload.
What is going on to cause [object Object] to replace all my form data when I include a file? Using remotipart 1.2.1. And I've seen this and it does not apply.
There are a lot of issues with attempting what you are:
Cross Domain Requests (CORS)
Form
Uploading
CORS
Your first issue is you have to ensure you're able to pass the data between the two domains. CORS is a standard protocol, whereby you can only send requests to pre-approved domains
Basically, you need some way to whitelist the possible connecting domains, and with Rails, you'll be best to use the RACK-CORS gem
I would begin by ensuring this is set up on your "receiving" domain
Form
Secondly, you need to compile the correct form data when you submit
I would use the .serialize() function:
$(document).on("click", ".application-form .submission input", function(e){
e.preventDefault();
var form = $(".application-form form");
var data = form.serialize();
var url = "http://example.com/action";
$.ajax({
url: url,
type: 'POST',
success: function(){
alert('success');
},
error: function(){
alert('error');
},
data: data,
cache: false,
contentType: false,
processData: false
});
});
This will probably explain the lack of params being sent to your other domain
Upload
Uploading files creates a totally new issue, as it takes a lot to get the file-upload process to work through ajax
There are plugins such as JQuery-FileUpload-Rails allow you to upload files through ajax. From my understanding, this works by providing custom middleware to handle the file upload over ajax. I'm not totally sure how it works, but I know it does, as we've used t multiple times
In general, you cannot directly upload files from a form via AJAX. You have to 'fake' it using either a hidden iframe, Flash, or something similar (might be different in the newest browsers). The jQuery Form plugin does a good job of simplifying this, and there are lots of other plugins as well to help with this.
This is my jquery code
$.ajax({
url: "PopUpProductDetails.aspx",
cache: false
}).done(function (html) {
$("#dialog").append(html);
});
The first time, it works just fine. It display the content of the PopUpProductDetails.aspx page. But, after that, If I click again, I get twice the same content, and so forth. I believe the problem is that I need to clear the dialog element first, before appending new content.
How do I do that?
.append() appends html to the end of existing html string, use .html() to replace what's currently inside of #dialog.
Inside the function clear the dialog first and then fill up with the content
$.ajax({
url: "PopUpProductDetails.aspx",
cache: false
}).done(function (html) {
$("#dialog").html("");
$("#dialog").html(html);
});
You can use .empty() first, then use .append() in one line :)
like this:
$.ajax({
url: "PopUpProductDetails.aspx",
cache: false
}).done(function (html) {
$("#dialog").empty().append(html);
});
in case you need to clear the dialog first use .empty() which is faster than .html("")
see Jquery Difference .html("") vs .empty()
I've used sortable/portlet jquery ui plugin on my website. I load some boxes after the page is loaded via ajax. but they don't look like the boxes appears at the page load time. I know the problem loading via ajax and bind issue. But how can I solve it?
You're ajax call has a success method which you can use to bind to elements that have been dynamically added.
For example you could do
$.ajax({
url: 'ajax/test.html',
success: function(data) {
$('.result').html(data);
$(".column").sortable({ connectWith: ".column", cursor: 'crosshair' });
}
});
If my 'create' action takes a while to load (due to doing an API call and then a calculation) what's the best way to show the user a 'loading screen' while this task is performed in the background?
Write some AJAX magic ;) Show the loading image when activated and hide it when the AJAX call is complete. And if you don't want to use AJAX, well, hmm, you could check out this:
http://yehudakatz.com/2010/09/07/automatic-flushing-the-rails-3-1-plan/
There's also a gem out there, that somewhat does that.
But I don't have any experience with that.
I would go for the AJAX method =)
EDIT:
Yeah, you should call the create action with AJAX in jQuery. You could do:
function create() {
$('#loading_image').show();
$.ajax({
type: 'POST',
url: /* URL to your create action: e.g. '/user/create/' */,
data: $('form').serialize(),
success: createSuccessHandler,
error: createErrorHandler,
complete: hideLoadingImage
});
}
function createSuccessHandler(data) {
alert("User created!")
}
function createErrorHandler(data) {
alert("It failed, ffs!")
}
function hideLoadingImage() {
$('#loading_image').hide()
}