I have a class based view that displays a page and handles POST requests, like so:
class citywall (View):
def get(self, request, *args, **kwargs):
template_name = 'citywall.html'
city_slug = kwargs['city_slug']
context = self.get_context_data(city_slug)
return render_to_response(template_name, context, RequestContext(request))
def post(self, request, *args, **kwargs):
if request.is_ajax:
if request.POST.has_key('comment'):
#process comment
...
if request.POST.has_key('vote'):
#process vote
...
The problem is when I try to POST the form with AJAX, two requests are being sent. The Ajax request and then a regular POST request.
This is my comment form in html:
<form class="comment_form" data-id="{{post.id}}" method="POST" >{% csrf_token %}
<textarea rows = "1" name="comment" class="form-control" placeholder="Write a comment..." ></textarea>
<button type="submit" class="btn btn-info">Go!</button>
</form>
This is the jQuery code:
var comment_form = $('.comment_form')
comment_form.submit(function(){
var post_id = $(this).data('id');
var comment = $(this).find('textarea[name="comment"]').val();
$.ajax({
url: "",
dataType:"json",
type:"POST",
data:{
comment: comment,
post_id: post_id,
csrfmiddlewaretoken:'{{csrf_token}}',
},
success:function(json)
{
alert(json);
},
});
});
When I submit the form this is happening:
AJAX POST is made with its json data(post_id, comment, csrf).
Response for the AJAX post is received back in browser.
POST is made with html form data(comment and csrf).
why is a second POST being made?
I have several types of forms on the page for example. comment form, voting form, etc and I want to make all of them AJAX. Is it a good idea to implement all of them with the above mentioned method?
The second POST with your form data is sent because your submit event handler doesn't return False. If you want to prevent the form from submitting when clicking the submit button, you have to return False in the event handler. The event handler can also be told to prevent form submission by calling e.preventDefault() on the event object that is being passed to the submit handler.
The reason for this behaviour is that, by default, the event fired when a submit button is clicked submits the forms at the very end of the event handling chain. So what happens is that in your event handler you are send a AJAX POST call (which is asynchronous), and the very next moment the handler returns without prevent the event from form submission. This results in both AJAX and form being sent.
e.preventDefault() tells the event e to avoid doing the default action specific to this event, in this case form submission. With this added, when $.ajax finishes and all the handlers are done handling the event the default handler is checked if it's allowed to be run. Since you have prevented it, nothing happens.
The very same method can be used to, e.g. prevent the webpage following a link <a> when clicked.
Related
I want to submit two form into two url and want to submit from two another functions of a Controller.
<form method="post" url="{ '/url1' }">
</form>
<form method="post" url="{ '/url2' }">
</form>
<button type="submit">Submit</button>
Is it possible to do without AJAX??
Simple answer : no, without ajax you can't send two requests.
Complicated answer: unless the first one carries the data for both then in the first response, it sends the second request with the data for it. Which is so complicating things, you should just do it in one request.
You can use jQuery to submit both forms like in the example below:
First of all, add an id to your button like this
<button type="submit" id="submitBtn">Submit</button>
Add ID to your forms:
form method="post" id="form1" url="{ '/url1' }">
form method="post" id="form2" url="{ '/url2' }">
I don't know what is wrong with the stakoverflow editor, that is why i deleted the "<" sign.
3. Now handle the jQuery click event:
$(document).ready(function(){
$('#submitBtn').on('click',function(){
$('#form1').submit();
$('#form2').submit();
});
});
You could give the forms different ids but same action.
Then in the controller called by the submit button, let IF statements check for the form ids and return the respective view desired eg
$requests = $request->all();
$form_Id = $requests['form1_Id'];
if($form_Id != 'id_of_first_form') {
return view('url2');
}else{
return view('url1');
}
If you have a main page form and a modal form and you wanna submit both in order, you can do it with javascript like this
// cause double submits at once
function doubleSubmit()
{
$.post($('#recordPaymentForm').attr("action"), $('#recordPaymentForm').serialize(), function(response) {
$('#submitEditOrderButton').trigger('click');
});
return false;
}
Leave your main page form as it is and change your modal form on submit attribute like this
<form id="recordPaymentForm" method="POST" action="/orders/{{$order->id}}/payments" onsubmit="return doubleSubmit(event)">
Please not that we first submit modal form and then we trigger on click event of submit button (submitEditOrderButton) on the main page. In this example, we first submit payment form and then we trigger click event of main page form which cause a form submit on the main page.
Trying to render all the Contacts using ajax (This is a snippet)
So on click, it will list the contacts in a div on the update action. I have tested with a basic date function (see commented out render action Controller) to make sure ajax part could work and that does, but handling the list I have hit a wall with and going round in circles
GSP:
<g:remoteLink controller="event" action="showContacts" update="divContactList">Show Contacts!</g:remoteLink>
<div id="divContactList">Show contacts Here...
<g:each in="${contactList}" status = "i" var="contact">
<p>${contact.forname}</p>
<p>${contact.email}</p>
</g:each>
</div>
Controller:
def showContacts = {
def contactList = Contact.findAllByUser(lookupPerson())
// render "The time is now ${new Date()}"
render([contactList: contactList])
}
So overall it's not showing anything from the contactList in the web page, help on this would be appreciated
_templateName.gsp:
<g:each in="${contactList}" status = "i" var="contact">
<p>${contact.forname}</p>
<p>${contact.email}</p>
</g:each>
GSP:
<g:remoteLink controller="event" action="showContacts" update="divContactList">Show Contacts!</g:remoteLink>
<div id="divContactList">Show contacts Here...
<g:render template="layouts/templateName" model="[contactList: contactList]" />
</div>
Controller:
def showContacts = {
def contactList = Contact.findAllByUser(lookupPerson())
// render "The time is now ${new Date()}"
render(template: 'layouts/templateName', model:[contactList: contactList])
}
Clicking the remote link will send an AJAX call to the showContacts action, get an HTML answer and update the content of divContactList with the returned answer.
The showContacts action will render a template with the same name, passing it the contactList as part of the model.
If you would like the AJAX call to render the list of contacts you can try one of the following options:
Content Centric Ajax - Have the showContacts action render a template which displays the list of contacts
Data Centric Ajax - Have the showContacts action send a JSON/XML response representing the list of contacts and have a client side JavaScript code render this JSON/XML as the contact list
I'm trying to map a button action to the controller function.
When I tried with :
#RequestMapping(method = RequestMethod.POST)
public void processValidateGenerate
....
and
<input type="button" id="continue" name="continue"...>
that works just fine, but now i want to add another button, so to differentiate betweent them I added so for the first action :
#RequestMapping(method = RequestMethod.POST, params="continue")
public void processValidateGenerate
....
but the function is not called anymore when the button is pressed, I think that works only for a submit input.
Are there any solution to do this with a non submit input ?
Thank you
You can use javascript/jquery to do an ajax call and hit the required controller method.
function doSomething(){
$.ajax({ //This is a jquery ajax call. You need to inlude jquery js files to do
type: "POST", // this operation
url: //URL,
data: //JSON data
}).done(function( msg ) {
alert( "Operation done: " + msg );
window.location.href=contextPath+"/newURL"; //If you want to go to a new page
});
}
now add the new button (It doesn't matter even it isn't a button, a div would suffice). Use the onclick function and give the javscript function name.
<input type="button" id="newcontinuebutton" name="continue" onclick=doSomething()...>
You can check the jquery ajax details here
I think this would help you.
I'm using a so as to edit an object, with an <input type="submit"> for validation
I've also another input, type="button" with an onclick event for the cancel button (with a redirect). However, this use a JS call, which I'd like to avoid.
I'd rather prefer to process the validation or cancel choice within the controller, so as to be NoScript compliant.
So is it possible to retrieve, within the controller post method, the id of the <input> that was clicked in the <form>?
Thanks
You can set the name of your
<input type="submit" name="submitButton" />
Then in your controller:
if(Request["submitButton"] != null) {
// ...
}
I'm not sure if I understand you, but if your cancel button does a redirect, it should end in a GET, and your submit button does a POST, that's how you should difference both request.
Check the [HttpPost] attribute in controller action methods.
I have an MVC 3 view for rendering reports from SQL Server Reporting Services. There's a form at the top where I capture parameters for the report and on submission, my controller action is dutifully called and my report is rendered into a < div >.
I'm now adding an Export to Excel function. I want the same parameters from the form, but this time, I want a full Postback, not an Ajax call to the controller, so that the user is offered the opportunity to download the report. Otherwise, my report gets rendered as binary content on the existing view.
I'm thinking that I want to be able to switch the behaviour of my form between Ajax and normal Postback, depending on which 'submit' button I click.
Any ideas?
#using (Html.BeginForm("Export", "Report"))
{
... some form fields
#Html.ActionLink("Render report", "Render", "Report", null, new { id = "generateReport" })
<input type="submit" value="Export to Excel">
}
<div id="report"></div>
and then AJAXify the Render report link in a separate js file:
$(function() {
$('#generateReport').click(function() {
var form = $(this).closest('form');
$.post(this.href, form.serialize(), function(result) {
$('#report').html(result);
});
return false;
});
});
and in your ReportController you would have both Export and Render actions.