I am building a web application that involves forms. The framework being used is symfony2. I would like to have everything working for users without javascript, and then progres
As long as you can generalize the sort of response needed for non-ajax forms and for ajax forms, you can relegate that decision of ajax/non-ajax to another method and then simply have:
return handleResponseType(whateverInfoIsNeededToHandleIt)
You then have full control over what gets passed in to your deciding function.
Another option is to have your controller return something other than a response and use the kernel.view
event to transform that into what you want. This would be better DRY because the logic is encapsulated in the listener. You just need to decide what you want your controllers to return.
if ($form->isValid()) {
return new Something($redirectUrl, $ajaxData);
}
And in your listener:
public function onKernelView($event)
{
$request = $event->getRequest();
$result = $event->getControllerResult();
if ($result instanceof Something) {
if ($request->isXmlHttpRequest()) {
$event->setResponse(new Response(json_encode($result->getAjaxData())));
} else {
$event->setResponse(new RedirectResponse($result->getRedirectUrl()));
}
}
}
You can return a response like usual and decide on the view if you want to do a partial render or render the whole page by extending different twig layouts.
In your controller:
if ($form->isValid()) {
// perform some action, such as saving the task to the database
$this->get('session')->setFlash('notice', 'Success!');
return $this->render('success.html.twig');
} else {
$this->get('session')->setFlash('notice', 'Please correct the errors below');
}
And in your views:
{# new.html.twig #}
{% extends app.request.isXmlHttpRequest ? 'ajax.html.twig' : 'layout.html.twig' %}
{% block content %}
{% if app.session.hasFlash('notice') %}
<div class="flash-notice">{{ app.session.flash('notice') }}</div>
{% endif %}
<form ...>
{{ form_widget('form') }}
<input type="submit" />
</form>
{% endblock %}
{# success.html.twig #}
{% extends app.request.isXmlHttpRequest ? 'ajax.html.twig' : 'layout.html.twig' %}
{% block content %}
{% if app.session.hasFlash('notice') %}
<div class="flash-notice">{{ app.session.flash('notice') }}</div>
{% endif %}
{% endblock %}
{# ajax.html.twig #}
{% block content %}{% endblock %}
{# layout.html.twig #}
<html>
<body> normal page content
<div id='content'>
{% block content %}{% endblock %}
</div>
</body>
</html>
(You might want to put the flash messages part in a macro or an include...)
Now simply render the return from the ajax request into the tag you want to place it:
$.ajax({
type: "POST",
url: "tasks/new",
data: {task: foo, dueDate: bar},
}).done(function( msg ) {
$('#content').html(msg);
});