MVC Async Postback & RenderPartial - asp.net-mvc-3

Apologies if the Title is a bit misleading, I'm just not sure how to go about doing this.
Ok here's the scenario. I am developing a feedback mvc widget that is housed in a Sitefinity 5.1 website. This widget is effectively just a div that is displayed when the user hovers over the feedbackLaunch label using jquery.
VIEW / WIDGET
#using (Html.BeginFormSitefinity())
{
<label for="feedbackLaunch">
<span class="FeedbackHighlight feedbackLaunch">Feedback</span>
</label>
<div class="feedback">
</div>
<div class="FeedbackContent" style="display: none">
<h1>Feedback</h1>
<h2>I thought this page was:
<br />
<br />
#Html.DropDownListFor(x => x.PageRatingId, new SelectList(Model.Rating, "PageRatingId", "PageRatingName"))
<br /><br />
Please give further detail:
<br /><br />
#Html.TextAreaFor(model => model.PageDetails, new { #style = "height: 100px;" })
<br /><br />
<input type="submit" value="Submit" />
</h2>
</div>
}
So I have a rendered page in the background with this feedback div now popped up. Lovely.
However, what I now want to do is do a submit click but without doing a postback, since the feedback div would disappear. Upon submission, I would essentially displaying a new div, or view, informing the info has been posted sent (that'll be fired off to a webservice).
What would be the best approach to do this?
Should I have two partial views, one for the submission form and the other for the "Thank you" section?
I have mentioned Sitefinity just in case there are any gotchas involved with that given it's quite a new feature of the CMS.
Any pointers gratefully received.

You could use AJAX with jQuery. For example give your form an id and then AJAXify it once you show the widget in your view:
$('#feedbackForm').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
alert('thanks for submitting your feedback');
// TODO: hide the div containing the feedback form
}
});
return false;
});

If your "Thank you" does not have any dynamically generated content, then just fire an AJAX call to some controller action and when you get a 200 response back just replace the div with a new one with the thank you, all using jQUery.
If you do need to dynamically generate the thank you on the server, then fire the ajax call to an action that returns a partial with the thank you message and once again use jquery to replace the original div with the contents of the response.

Related

Play framework write Action with Ok(...) that doesn't load new page

Play framework 2.4.x. A button is pressed on my home page that executes some code via Ajax, and returns its results beneath the button without loading a new page. The results wait for a user to input some text in a field and press "submit". Those results Look like this:
<li class="item">
<div>
<h3>Email: </h3>
<a>#email.tail.init</a>
<h3>Name: </h3>
<a>#name</a>
</div>
<div>
<h3>Linkedin: </h3>
<form class="linkedinForm" action="#routes.Application.createLinkedin" method="POST">
<input type="number" class="id" name="id" value="#id" readonly>
<input type="text" class="email" name="email" value="#email" />
<input type="text" class="emailsecondary" name="emailsecondary" value="" />
<input type="text" class="name" name="email" value="#name" />
<input type="text" class="linkedin" name="linkedin" value="" />
<input type="submit" value="submit" class="hideme"/>
</form>
</div>
<div>
<form action="#routes.Application.delete(id)" method="POST">
<input type="submit" value="delete" />
</form>
</div>
</li>
Along with some jquery that slides up a li after submission:
$(document).ready(function(){
$(".hideme").click(function(){
$(this).closest('li.item').slideUp();
});
});
However, since a form POST goes inside an Action that must a return an Ok(...) or Redirect(...) I can't get the page to not reload or redirect. Right now my Action looks like this (which doesn't compile):
newLinkedinForm.bindFromRequest.fold(
errors => {
Ok("didnt work" +errors)
},
linkedin => {
addLinkedin(linkedin.id, linkedin.url, linkedin.email, linkedin.emailsecondary, linkedin.name)
if (checkURL(linkedin.url)) {
linkedinParse ! Linkedin(linkedin.id, linkedin.url, linkedin.email, linkedin.emailsecondary, linkedin.name)
Ok(views.html.index)
}else{
Ok(views.html.index)
}
}
)
Is it possible to return Ok(...) without redirecting or reloading? If not how would you do a form POST while staying on the same page?
EDIT: Here is my attempt at handling form submission with jquery so far:
$(document).ready(function(){
$(".linkedinForm").submit(function( event ) {
var formData = {
'id' : $('input[name=id]').val(),
'name' : $('input[name=name]').val(),
'email' : $('input[name=email']).val(),
'emailsecondary' : $('input[name=emailsecondary]').val(),
'url' : $('input[name=url]').val()
};
jsRoutes.controllers.Application.createLinkedin.ajax({
type :'POST',
data : formData
})
.done(function(data) {
console.log(data);
});
.fail(function(data) {
console.log(data);
});
event.preventDefault();
};
});
This is an issue with the browser's behavior on form submission, not any of Play's doing. You can get around it by changing the behavior of the form when the user clicks submit.
You will first want to attach a listener to the form's submission. You can use jQuery for this. Then, in that handler, post the data yourself and call .preventDefault() on the event. Since your javascript is now in charge of the POST, you can process the data yourself and update your page's HTML rather than reloading the page.
What you need is use ajax to submit a form, check this: Submitting HTML form using Jquery AJAX
In your case, you can get the form object via var form = $(this), and then start a ajax with data from the form by form.serialize()
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data: form.serialize(),
success: function (data) {
alert('ok');
}
});
In order to accomplish this task, i had to use play's javascriptRouting
This question's answer helped a lot.
I'm not experienced with jquery so writing that correctly was difficult. For those that find this, here is my final jquery that worked:
$(document).ready(function(){
$("div#results").on("click", ".hideme", function(event) {
var $form = $(this).closest("form");
var id = $form.find("input[name='id']").val();
var name = $form.find("input[name='name']").val();
var email = $form.find("input[name='email']").val();
var emailsecondary = $form.find("input[name='emailsecondary']").val();
var url = $form.find("input[name='url']").val();
$.ajax(jsRoutes.controllers.Application.createLinkedin(id, name, email, emailsecondary, url))
.done(function(data) {
console.log(data);
$form.closest('li.item').slideUp()
})
.fail(function(data) {
console.log(data);
});
});
});
Note that my submit button was class="hideme", the div that gets filled with results from the DB was div#results and the forms were contained within li's that were class="item". So what this jquery is doing is attaching a listener to the static div that is always there:
<div id="results">
It waits for an element with class="hideme" to get clicked. When it gets clicked it grabs the data from the closest form element then sends that data to my controller via ajax. If the send is successful, it takes that form, looks for the closest li and does a .slideUp()
Hope this helps

My .ajax call isn't working

I have a form on my website that pushes to my e-mail address. Previously before I wrote an ajax function the form would successfully push to my e-mail address. Only problem is when the user fills out the form it takes them to another page upon submitting the form. The HTML for my form is below.
<form id="contact" method="post" action="E-mail-form.php" name="EmailFromMyWebsite">
<label for="name">Name</label> <br>
<input type="text" name="name" class="required" placeholder="Your Name" title=" (Your name is required)"> <br />
<label for="email">E-mail</label> <br>
<input type="email" name="email" class="required email" placeholder="Name#email.com" title=" (Your email is required)"> <br />
<label for="message">Message/Comment</label> <br>
<textarea name="message" class="required" placeholder="Leave a brief message" title=" (Please leave me a brief message)"></textarea> <br />
<input type="submit" name="submit" id="submit" value="Send Message" />
</form>
</div><!-- /end #contact-form -->
The ajax call I wrote is...
$("#submit").on('click', function(){
var formData = $('#contact').serialize();
$.ajax({
type:"POST",
data:"formData",
url:"Email-form.php",
success: function(data){
$('#contact').html('<p>Your message has been sent</p>');
}
});
});
My javaScript console shows no errors so I think the problem is with my jQuery logic. On Chrome when I click submit I am redirected to my homepage. On Firefox the form submits but I am redirected to another page, therefore it is completely ignoring my AJAX call. Can someone with AJAX experience tell me what I'm doing wrong? Also I would love to attach a message if the call fails. Can I add 'failure:' and for the value put a function just like I did for success?
You have two issues
your form is submitting normally
you're attempting to post the wrong data
To prevent the form from submitting you can return false from the jQuery click handler or call preventDefault from the event object.
You are sending a string "formData" as the form data instead of the string in the formData variable
$("#submit").on('click', function(event){
var formData = $('#contact').serialize();
$.ajax({
type:"POST",
data:formData,
url:"Email-form.php",
success: function(data){
$('#contact').html('<p>Your message has been sent</p>');
}
});
event.preventDefault();
// or
return false;
});
There's a good chance that the normal form submit action is still taking place, even though you have an AJAX call as well. An easy fix for this may be to simply change the button type from submit to button. That way your click handler will still work, but it won't perform the default action of submitting the form on its own.
<input type="button" name="submit" id="submit" value="Send Message" />

How to show flash.message in Grails after AJAX call

I want to show some flash message after completion of AJAX call. I am doing like this ..
Controller Action --
def subscribe()
{
def subscribe = new Subscriber()
subscribe.email = params.subscribe
if (subscribe.save())
{
flash.message = "Thanks for your subscribtion"
}
}
View Part --
Subscribe :
<g:formRemote onSuccess="document.getElementById('subscribeField').value='';" url="[controller: 'TekEvent', action: 'subscribe']" update="confirm" name="updateForm">
<g:textField name="subscribe" placeholder="Enter your Email" id="subscribeField" />
<g:submitButton name="Submit" />
</g:formRemote >
<div id="confirm">
<g:if test="${flash.message}">
<div class="message" style="display: block">${flash.message}</div>
</g:if>
</div>
My AJAX working fine but it is not showing me flash.message. After refresh page it displaying message. How to solve it ?
When you use ajax your page content isn't re-parsed, so your code:
<g:if test="${flash.message}">
<div class="message" style="display: block">${flash.message}</div>
</g:if>
will not run again.
So I agree with #James comment, flash is not the better option to you.
If you need to update your view, go with JSON. Grails already have a converter that can be used to this:
if (subscribe.save()) {
render ([message: "Thanks for your subscribtion"] as JSON)
}
And your view:
<g:formRemote onSuccess="update(data)" url="[controller: 'TekEvent', action: 'subscribe']" name="updateForm">
<g:textField name="subscribe" placeholder="Enter your Email" id="subscribeField" />
<g:submitButton name="Submit" />
</g:formRemote >
<script type='text/javascript'>
function update(data) {
$('#subscribeField').val('');
$('#confirm').html(data.message);
}
</script>
You have couple options,
First you can try to return the message from your controller in a form of json or a map and render it on the screen your self using javascript libraries, which is a bit different if you want to use Grails ajax tags.
The other option is using a plugin like one-time-data , which
Summary A safe replacement for "flash" scope where you stash data in
the session which can only be read once, but at any point in the
future of the session provided you have the "id" required.
Description
This plugin provides a multi-window safe alternative to flash scope
that makes it possible to defer accessing the data until any future
request (so long as the session is preserved).
more
Hope it helps

Jquery Mobile - search input has no value on post after AJAX loaded content

I am having an issue where when a page is loaded via Ajax, I don't have a value in my search input. Here is my HTML:
<form id="searchForm" action="javascript:;" method="post">
<div>
<input type="search" name="search-mini" id="search-mini" value="" data-mini="true" />
<input type="submit" data-mini="true" value="Search" />
</div>
</form>
The reason we have an input button is because of a request from the client as they found people having scenarios where they would click "Done" on the IOS keyboard rather than "Search" which wouldn't submit the form. here is my Javascript that handles the submit:
$(document).on('submit', '#searchForm', function () {
var text = $("#search-mini").val();
text = encodeURIComponent(text);
window.location.href = "/Mobile/Browse/Text?text=" + text;
return true;
});
This all runs fine if I refresh the page so the content is not loaded via AJAX. It only fails when linking between pages and they are loaded by AJAX. Alerting out "text" has a blank value in this scenario.
I have read about using JQM initialization events such as 'PageInit' instead of DOM ready() I just need an example implementing this with my code if this is the correct approach?
Regards,
Danny

Ajax form perfect until inside another page

I have a page which uses ajax to submit a comment form, add it to a db, then redisplay the page, hopefully without reloading the page its on.
If I access the script on it's own it works great, yet when I load it into another page it doesn't add the data and also refreshes the page on submit, which I want to avoid, which is the whole point of doing things this way.
Anyway, here's how I load the page:
<div id="wall_comments" class="msgs_holder"></div>
<script type="text/javascript">
$('#wall_comments').load('/pages/comment.php', { wl_id:"<?=$wl_id?>" });
</script>
and then the page itself with jquery code:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<div style="width:100%; overflow:auto;">
<form method=post>
<input type="text" class="inp" name="comment" id="comment">
<input type=submit value="do it" name="action" onclick="update()">
<input type=hidden name="wl_id" value="<?=$_REQUEST[wl_id]?>" id="wl_id">
<input type=hidden name="user_id" value="<?=$userfromcookie?>" id="user_id">
</form>
</div>
<script type="text/javascript">
function update(){
var wl_idVal = $("#wl_id").val();
var commentVal = $("#comment").val();
var user_idVal = $("#user_id").val();
$.ajax({
type: "POST",
url: "/pages/comment.php",
cache: false,
data: { submit: "", wl_id: wi_idVal, comment: commentVal, user_id: user_idVal }
});
}
</script>
And finally enter info into db (I know this should be mysqli and it will be)
if(isset($_POST['action'])){
$wl_id = mysql_real_escape_string($_POST['wl_id']);
$comment = mysql_real_escape_string($_POST['comment']);
$user_id = mysql_real_escape_string($_POST['user_id']);
$addcomment = mysql_query("insert into list_wall (
event_id,
user_id,
comment
) VALUES (
'$wl_id',
'$user_id',
'$comment'
) ",$db);
if(!$addcomment) { echo 'result error add comment'; echo mysql_error(); exit; } // debug
}
The problem is when you click the submit button, the page is submitted and the function update couldn't work. You have to cancel the default submit mechanism by using return false;
<input type=submit value="do it" name="action" onclick="update() return false;">
Another thing.
The onclick on the submitbutton will not work as excpected if the submit is caused without clicking the button.
For example mobile safari on iPhone can submit forms directly without triggering the button.
If you add UmairP's version of the onclick to the form element as an onsubmit method you should get the same result on every platform as far as I know.
You can see more details on iPhone forms in my own question on another issue.
How can I prevent the Go button on iPad/iPhone from posting the form

Resources