Reputation: 9428
I have a footer template which has a input and submit for email subscription. The footer is used by every page. When subscription succeeds, it will redirect back to current page. However, I found out I am passing a string value to indicate what current page is. What is the best way to have a footer template for Play 2.0 application?
footer.scala.html
@(page: String)
<div id="footer">
<div class="input-append">
<form action="@routes.ApplicationController.saveSubscription(page)"
method="post">
<input type="text" name="emailAddress" placeholder="Your Email" />
<input class="btn" type="submit" value="Subscribe" />
</form>
</div> <!-- /input-append -->
</div> <!-- /footer -->
ApplicationController.java
public class ApplicationController extends Controller {
public static Result saveSubscription(String page) {
..........
flash("success", "success message");
if (page.equals("page1")) {
return redirect(routes.ApplicationController.page1());
} else if (page.equals("page2")) {
return redirect(routes.ApplicationController.page2());
}
}
}
page1.scala.html
@main("Page 1") {
<div>
<p>page 1</p>
</div>
@footer("page1")
}
page2.scala.html
@main("Page 2") {
<div>
<p>page 2</p>
</div>
@footer("page2")
}
EDIT 1
I follow @virtualeyes but it seems the subscribe.js is never been called. Here is the New setup.
main.scala.html
<html>
<head>
<script type="text/javascript" src="@routes.Assets.at("javascripts/jquery.min.js")"></script>
<script type="text/javascript" src="@routes.Assets.at("javascripts/vendor/jquery.validate.min.js")"></script>
<script src="@routes.Assets.at("javascripts/main.js")" type="text/javascript"></script>
<script src="@routes.Assets.at("javascripts/subscribe.js")" type="text/javascript"></script>
</head>
<body>
@footer()
</body>
</html>
footer.scala.html
<div id="footer">
<div class="input-append">
<form id="_form" action="@routes.ApplicationController.simpleSubscription()">
<input type="text" name="emailAddress" placeholder="Your Email" />
<input id="_process" class="btn" type="submit" value="Subscribe" />
</form>
</div> <!-- /input-append -->
</div> <!-- /footer -->
routes
POST /subscribe controllers.ApplicationController.simpleSubscription()
Now I got his error: Action not found For request 'GET /subscribe?emailAddress=fdsaf%40rte.com'
I am not sure if it is because method="post" is removed. If I put it back, then the result will return but will redirect to /subscribe page. I also set a breakpoint at subscribe.js but it doesn't seem to be called at all.
EDIT 2 - Working
after I changed a little bit for subscribe.coffee and get rid of main.coffee, now it's working.
subscribe.coffee
$('#_process').click (e) ->
e.preventDefault()
isValid = $('#_form').validate().form()
if isValid
$('#_process').spin()
$.ajax
type: "POST"
url: $('#_form').attr('action')
data: $('#_form').serialize()
success: (data) ->
$('#_status > div').removeClass('alert-error').addClass('alert-success')
$('#_status > div').html( data )
$('#_status').fadeIn()
fade = () -> $('#_status').fadeOut('slow')
setTimeout fade, 2000
$('#_process').spin('stop')
error: (data) ->
$('#_status > div').removeClass('alert-success').addClass('alert-error')
$('#_status > div').html( data.responseText )
$('#_status').fadeIn()
fade = () -> $('#_status').fadeOut('slow')
setTimeout fade, 2000
$('#_process').spin('stop')
complete: () -> $('#_process').spin('stop')
footer.scala.html
<div id="_status">
<div class="alert alert-error"></div>
</div>
<div class="input-append">
<form id="_form" action="@routes.ApplicationController.simpleSubscription">
<input type="text" name="emailAddress" placeholder="Your Email" />
<input id="_process" class="btn" type="submit" value="Subscribe" />
</form>
<div id="_spin"></div>
</div> <!-- /input-append -->
The spin() function is from https://github.com/pshizzle/spin.coffee
Upvotes: 1
Views: 578
Reputation: 11237
AJAX is the way™
//footer.scala.html
<div id="footer">
<div class="input-append">
<form id="_form" action="@routes.ApplicationController.saveSubscription">
<input type="text" name="emailAddress" placeholder="Your Email" />
<input id="_process" class="btn" type="submit" value="Subscribe" />
<img id="spinner" src="/assets/img/loader.gif" alt="loading..." />
</form>
</div>
</div>
<div id="status">
<div class="alert alert-error"></div>
</div>
<style type="text/css">
#spinner, #status { display: none; }
</style>
//ApplicationController.java
public class ApplicationController extends Controller {
public static Result saveSubscription() {
// save subscription
...
// pseudo code
if(success)
Ok( i18n("subscription success").toJson() );
else
Conflict( i18n("subscription fail").toJson() );
}
}
//main.coffee
jQuery ->
$.ajaxSetup
type: "POST"
cache: false
dataType: "json"
# prevent form submit on keypress
$('form').find('input').keypress (e) -> e.preventDefault() if(e.which == 13)
jParse = (data) ->
try jQuery.parseJSON(data)
catch e
data
jText = (data) -> jParse(data.responseText)
toSuccess = (msg) ->
$('#status > div').removeClass('alert-error').addClass('alert-success')
$('#status > div').html( jParse(msg) )
$('#status').fadeIn()
toFail = (data) ->
$('#status > div').html( jText(data) )
$('#status').fadeIn()
//subscribe.coffee
jQuery ->
$('#_process').click (e) ->
e.preventDefault()
isValid = $('#_form').validate().form() // assumes jQuery validation plugin
if isValid
$('#spinner').show()
$.ajax
data: $('#_form').serialize()
success: (msg) ->
toSuccess(msg)
fade = () -> $('#status').fadeOut('slow')
setTimeout fade, 2000
error: (data) -> toFail(data)
complete: () -> $('#spinner').hide()
Upvotes: 2
Reputation: 55798
How about passing ready to use redirect address in hidden field?
footer
@(returnPath: String)
<form action="@routes.ApplicationController.saveSubscription()" method="post">
...
<input type="hidden" name="returnPath" value="@returnPath" />
</form>
page1
@main("Page 1") {
...
<!-- it's important to use toString at the end -->
@footer(routes.ApplicationController.page1.toString)
}
or even better: giving the path
from the current request()
@main("Page 1") {
...
@footer(request.path)
}
controller
public static Result saveSubscription() {
...
flash("success", "success message");
return redirect(form().bindFromRequest().get("returnPath"));
}
BTW: maybe it would be just easier and nicer to use AJAX form? in such case you are avoiding redundant reloads at all (and finding objects and rendering whole templates again and again, etc etc.)
Upvotes: 0