jQuery form processing, how can I reassign a function on callback? - javascript

$(function(){
$(".mailbutton").click(function() {
var email = $(".mailingfield").val();
$.post("/PHP_scripts/mailinglist.php", { email: email }, function(data) {
var content = $(data).find("#mailinglistform");
$("#box").empty().append(content);
});
});
});
I'm using this to process an email address. If it fails in the PHP script the form is sent back in the '.mailinglistform' with a fresh form and some text explaining the error. The problem I have is that even though the button has the '.mailbutton' class in the callback form, the button doesn't do anything on click.
Is this because the jQuery only recognises it first time round? If so, is there a way to "reload" the 'mailbutton' .click function on callback?
Thanks!

You're right that because you're only re-rendering a portion of the page, the previous jQuery you wrote does not register with the "new" mailbutton class that you've re-rendered. To get around this, you should use .on(), e.g.:
$(".wrapper").on('click', '.mailbutton', function() {
var email = $(".mailingfield").val();
$.post("/PHP_scripts/mailinglist.php", { email: email }, function(data) {
var content = $(data).find("#mailinglistform");
$("#box").empty().append(content);
});
});
In this case, wrapper needs to be a class element that's outside of the re-rendered section (e.g. the 'content' class, maybe a class around your form, etc) of the page, and one that is constantly present (i.e. not re-rendered in the ajax call). This will attach an onclick handler to any .mailbutton classes that are children of the wrapper class, whether they are present when the page is rendered, or if they are added to the DOM later.

Use on to bind click event. When control is render again in the callback function its events are removed. Using on instead of click could rebind the events automatically.
$(function(){
$(".mailbutton").on("click", function() {
var email = $(".mailingfield").val();
$.post("/PHP_scripts/mailinglist.php", { email: email }, function(data) {
var content = $(data).find("#mailinglistform");
$("#box").empty().append(content);
});
});
});

For this you can use AJAX with JQuery. OR you can alos user load().
$(".mailbutton").click(function() {
$.ajax({
url: 'api.php', // Put your calling page path here
data: "",
dataType: 'json',
success: function(data)
{
//do whatever you want to do on success
}
});
});

Related

Sending a POST request with Ajax on button click

I have a normal button, which triggers a basic function that prints the value of an element in my HTML to the console.
Now, instead of printing the value of that element i want to send it to my Django view with a POST request.
Here is the function:
$(document).on('click','.btnClick', function() {
var myvalue = $(this).data("myid");
console.log(myvalue);
});
Here, instead of printing that value, i want to send myvalue with a post request using Ajax.
I know how to do a POST request, the only difference is that this time, instead of using a form, i'm using a single button to trigger the request, and i'm not really used to that.
Here is how i would do it with a form:
$(document).ready(function () {
$("#myform").submit(function (event) {
$.ajax({
type: "POST",
url: "/myurl/",
data: {
'myvalue': $('id').val()
},
});
return false;
});
});
So, basically i just need to know how to integrate this piece of code inside the first function, so that the Ajax call is triggered not by the form (as it is in the second code) but from a button.
Just put your jquery ajax function inside into the click event function.
$(document).on('click','.btnClick', function() {
var myvalue = $(this).data("myid");
$.ajax({
type: "POST",
url: "/myurl/",
data: {
'myvalue': myvalue
},
});
});
Hope this will help.

How to get the id of a dynamically created form in jquery

I am using a Bootstrap modal to display an ASP.Net MVC5 form, the form is inserted dynamically into a div using a jquery ajax call to the relevant controller and then opened.
I need to intercept the submission of the form so I would like to bind to the submit event of the form in jquery but have so far only been able to bind to the submit event of all forms since the dynamic forms are of course not present when the main view is rendered e.g.
$('form').submit(...)
rather than
$('#serverForm').submit(...)
Whilst this sort of works, it has a problem in that I actually have 3 different dynamic forms in this view which can be shown using modal popups, thus I need to do one of 2 things:
A) (ideally)manage to intercept the submit event for each form.
B) in the global form event handler, identify which form has been submitted.
I have tried every option I can imagine to use option A including adding the binding to the code which pops the modal. all without success.
I am currently trying to go with option B so that I can then decide where to post the form. This does at least get called when a form is submitted but my problem is that I cannot get the id or name of the form which has been submitted and thus have no way of knowing which one it is.
I have the following handler:
<script>
$(function () {
$('form').submit(function(e) {
// this is always null
var id = $(this).attr('id');
$.ajax({
url: '#Url.Action("EditServer", "AccountAdmin")',
data: new FormData(this),
...
});
});
});
</script>
Within this handler I have tried the following (plus a few more!) to get the form's id:
this.id
$(this).id
$(this).attr('id');
$(this).prop('id');
I have tried adding the handler after the ajax call to populate the modal like this:
$(".server-link").click(function (event) {
event.preventDefault();
$.ajax({
url: $(this).attr("href"),
cache: false,
type: "GET",
dataType: "html",
success: function (data, textStatus, XMLHttpRequest) {
$('#serverDiv').html(data);
$('#serverModal').modal('show');
$('form').submit(function (e) {
var id = $(this).attr(id);
// test to see if handler called
alert(id);
});
},
error: function (jgXHR, textStatus, errorThrown) {
//The commented out message is full of Html but includes compilation errors etc from the server
//alert('An error occured: ' + jgXHR.responseText);
alert(textStatus + ':' + errorThrown);
}
});
});
It's driving me bonkers! I have tried every combination of ideas from various posts with no joy. I need to post using FormData (in one case at least) because there is a file upload (an image) involved. Any assistance is much appreciated.
The problem is that your JavaScript code is running before the form has actually been added to the page. When using AJAX, you need to run whatever JavaScript you need in the callback:
$.get('/some/url', function (result) {
$('#whatever').html(result);
$('form').submit(function(e) {
var id = $(this).prop('id');
// do whatever with id
});
});
Use this instead:
var id = $(e.target).attr('id');

Call JavaScript function from PagedListPager

Is it possible to call a JavaScript function from within #Html.PagedListPager(in here) ?
I have a button which calls the following function and performs all its supposed to with ease:
function fetchResults() {
$.get('#Url.Action("Search", "Notifications")',
{
device: "Device"
},
function (data) {
$('#results').html(data);
})
};
Now how can I do the same when I click on a page number on my PagedListPager?
Currently my pager reloads the page and that's the main thing I want to avoid.
This is my Pager:
#Html.PagedListPager((IPagedList)ViewBag.NotificationsPage, page =>
Url.Action("Search", "Notifications", new
{
device = "Device",
page = page
}),
PagedListRenderOptions.PageNumbersOnly)
Perhaps there's a much better way to do this. Help will be appreciated.
All that this #Html.PagedListPager helper does is spit some HTML containing links to perform the pagination. So you could subscribe to the click event of those links and AJAXify them:
$(document).on('click', 'a', function() {
$.ajax({
url: this.href,
type: 'GET',
cache: false,
success: function(result) {
$('#results').html(result);
}
});
return false;
});
Important things to note:
I have subscribed to the click event in a lively manner. This means that if we replace the links in the success callback of the AJAX request, this click event handler will continue to work
You might want to adjust the $(document).on('click', 'a', function() { selector which is pretty inclusive and target only the links generated by this pager. For example look if they are not inside some containing div or something in which case you could use something along the lines of $('.pager').on('click', 'a', function() {.
Inside the success callback you might need to adapt the $('#results') selector to target the div containing the actual results which will get refreshed with the partial HTML returned by your controller action.
Talking about partial HTML and controller action you will obviously need to adapt the controller action that gets invoked in the AJAX request to return a PartialView instead of a full View containing only the updated records and new pagination links.

How to apply the same rules defined in a JS file, containing all rules within document.ready(..) to new posts?

I have a simple JS file that uses Jquery to apply rules to the loaded page.
I starts with the traditional $(document).ready(function(){
Nevertheless, when I load more posts (load more button) or submit a new post, those rules don't apply. I think I understand why...though it is not clear.
Is there a way to apply the same rules to each new added post? Is the only way defining events directly on the html code like e.g onclick....?
I may be a very simple question. I'll appreciate any answers :)
Thanks
JS Code
$(document).ready(function(){
(...)
$('button#cancel').on('click',function () {
$(this).parents('.footer').hide();
$(this).parents('.footer').siblings('.small-textarea-main-feed').removeClass('set-large');
$(this).parents('.footer').siblings('.small-textarea-main-feed').val('');
});
(...)
}); closes all
I am using the following code in load_questions.js to load a new post:
$('form.ajax').submit(function() {
//
var that = $(this),
url = that.attr('action'),
type = that.attr('method'),
data = {};
that.find('[name]').each(function(index, value) {
var that = $(this),
name = that.attr('name'),
value = that.val();
data[name] = value;
});
//event.preventDefault();
$.ajax({
url: url,
type: type,
data: data,
cache: false, // it will force requested pages not to be cached by the browse
success: function(html){
console.log(html);
$("ol#list-feed").prepend(html);
$("ol#list-feed li:first").slideDown(600);
document.getElementById('set-width1').value='';
document.getElementById('tags').value='';
if ($("ol#list-feed > li").size() <= 3) {
$('#loadmorebutton').hide();
} else {
$("ol#list-feed > li:last").remove();
$('#loadmorebutton').show();
}
}
});
//event.preventDefault();
return false;
});
I want that this type of rules apply to new posts I submit.
The DOMDocumentReady event fires exactly once on the page, when the entire HTML document has been loaded and parsed, so any DOM element you should be able to expect be on the page, will be.
Any DOM elements you add to the page from this point on, need to be decorated again. This can be as simple as calling the DOMDocumentReady handler again, in which case you'd want to make it a named function, and pass that named function to $(document).ready(...). Something like this:
var onReadyHandler = function() { };
$(document).ready(onReadyHandler);
$.ajax({
success: function(html) {
$("ol#list-feed").prepend(html);
onReadyHandler();
}
});
Now, it's likely that a better way of handling this (it's really unclear to me what precisely you're trying to accomplish, but that's not a real problem), is to not bind anything to your new posts at all. If you're concerned about events, bind the events to the container you know will be on the page, using 'event delegation' (jQuery link: http://api.jquery.com/delegate/). This pattern takes advantage of the fact that events 'bubble' in the DOM, meaning you can listen higher in the DOM then the elements you actually want to respond to, and just check that the click event happened on the event you do care about ($.delegate does this check automatically). The end result? You bind far fewer event handlers, since you're not decorating each post individually.

jQuery: Submit a form only if no AJAX is currently running on the page

When the city input field is blurred I get somnething via an ajax request and set that as the value of a hidden field in the same form that the city field resides in.
$('input#city').on('blur', function() {
$.ajax({
url: 'get/something?param=val',
success: function(response) {
$('input:hidden[name="something"]').val(response);
}
});
});
If the user submits the form immediately after blurring off the city field sometimes due to latency the hidden field is not populated because the SQL on the other end is taking too long.
The form that both these fields are in is also submitted via ajax:
$('form#find-users').on('submit', function() {
if(NO_AJAX_CURRENTLY_RUNNING_ON_PAGE) {
// do stuff
}
});
How to detect if no ajax is running on the page? This will ensure that the city ajax was completed and the hidden field populated before the form is processed.
EDIT
Actually it won't, it will only prevent the form from being submitted. But if I can detect that then I can use a setInterval and keep trying to run that code until it runs because ajax is complete. Ideally there will be something in jQuery that waits until other ajax is complete and then submits.
Use jQuery's Ajax Events. As long as all of your Ajax calls are generated using jQuery, you have a way of knowing if any Ajax calls are outstanding.
$(document).ready(function() {
var ajaxBusy = false;
$(document).ajaxStart( function() {
ajaxBusy = true;
}).ajaxStop( function() {
ajaxBusy = false;
});
});
Edit:
So that answers your direct question about "How do I know if there is any Ajax call running."
Alternatively, you could disable the form's submit buttons when run your blur handler, and then re-enable it when you're done.
$('input#city').on('blur', function() {
var submit = $(this).closest('form').find(':submit:enabled');
submit.prop('disabled', true);
$.ajax('get/something?param=val').done(function(response) {
$('input:hidden[name="something"]').val(response);
}).always(function() {
submit.prop('disabled', false);
});
});
Edit 2:
So now we're at the point where we would like to delay the form submission until all current Ajax calls have completed. We let people click on the submit button, but if there are pending Ajax calls we don't do anything right away.
We can use a Deferred object to help us with this.
$(document).ready(function() {
var ajaxDefer = $.Deferred().resolve();
$(document).ajaxStart( function() {
ajaxDefer = $.Deferred();
}).ajaxStop( function() {
ajaxDefer.resolve();
});
$('form#find-users').on('submit', function() {
ajaxDefer.always(function() {
// Code here will always be executed as soon as there are no
// Ajax calls running.
// this points to the deferred object (ajaxDefer), so use the closure
// to carry over any variables you need.
});
});
});
When we're just starting out, we set up our ajaxDefer object in a resolved state. That means any functions attached using .always() will execute immediately.
When the first Ajax call starts, we replace the old ajaxDefer object with a new one that has not been resolved. Any new functions attached using ajaxDefer.always() will be deferred until later.
When the last Ajax call completes, we call ajaxDefer.resolve(), which causes any unexecuted deferred functions to execute. Now we're back to our initial state, where any newly-attached functions will execute immediately.
When somebody tries to submit the form, create an anonymous function that does the work and attach it to ajaxDefer. It will get executed when appropriate, depending on if there are any outstanding Ajax requests or not. Be mindful of your closures.
Use this to check if AJAX calls are currently in-progress using JQuery:
if ($.active == 0) {
...
}
you can put a variable in the global namespace, perhaps named ajaxLock and toggle it on when AJAX starts and off when the response comes. Then check it before allowing submit.
something like
var ajaxLock = 1;
$('input#city').on('blur', function() {
$.ajax({
url: 'get/something?param=val',
success: function(response) {
$('input:hidden[name="something"]').val(response);
ajaxLock = 0;
}
});
});
Use a lock variable like you suggested:
$('input#city').on('blur', function() {
window.AJAX_CURRENTLY_RUNNING_ON_PAGE = true;
$.ajax({
url: 'get/something?param=val',
success: function(response) {
$('input:hidden[name="something"]').val(response);
},
complete: function() { window.AJAX_CURRENTLY_RUNNING_ON_PAGE = false; }
});
});
$('form#find-users').on('submit', function() {
if(window.AJAX_CURRENTLY_RUNNING_ON_PAGE) {
return;
}
//dostuff
});
What i could have done on this circumstances is to use plugin like block ui or disable the form submit button,the reason is you need to be interactive in your design,you may well able to lock the form submission,but its better to give a message or have a modal gray out

Categories

Resources