Form does not display form errors in template - symfony

For my contact form no form errors are displayed.
$contact = new Contact();
$form = $this->createForm(new ContactFormType(), $contact);
/* handle contact form submission */
if ('POST' == $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
//Do something
}
}
return $this->render('MainBundle:Default:contact.html.twig', array(
'form' => $form->createView()
));
My validator
Fc\MainBundle\Entity\Contact:
properties:
firstName:
- NotBlank: ~
lastName:
- NotBlank: ~
email:
- NotBlank: ~
- Email:
checkMX: true
title:
- NotBlank: ~
message:
- NotBlank: ~
I have added a novalidate attribute to my form tag to check if my validation works. Now when I submit the form with empty data nothing happens (with correct data everything is fine), the controller identifies the form as invalid and stops further processes.
In the template I call
{{ form_errors(form) }}
But nothing is displayed. Any ideas why? I use symfony 2.1.X

Can you confirm that the validation is working with this:
if ($form->isValid()) {
//Do something
}
else
{ die('not valid') }
Is the form well posted?
Is there anything in the HTML that shows up where you call {{ form_errors(form) }} ? - it would be a CSS or JS problem if that's the case...
Have you tried to show the errors by field (there is no global error in your validation apparently):
{{ form_errors(form.firstName) }}
etc.
Remark: form.firstName works, not form.first_name. You have to follow that convention with Doctrine2/Symfony2.

Related

Symfony render controller

want to display a form in a modal in the header. In order to make the form work I call the controller Homecontroller.
I called the controller with render controller in the branch but I got a blank page.
Thanks for your help.
header.html.Twig
<h1 class="fw-bold"></h1>
<p class="lead fw-bold"></p>
{{include ('fragments/modal_form.html.twig') }}
</main>
</div>
</div>
modal_form.html.twig
{{ render(controller(
'App\\Controller\\HomeController::index',{'form' : form.createForm()} )) }}
</div>
Controller :
* #Route("/", name="home")
*/
public function index(PostsRepository $postsRepository,TagRepository $tagRepository, Request $request ):Response
{
$listTag = $tagRepository->findAll();
$listPost = $postsRepository->findByPostPHp('php');
$posts = $postsRepository->findByExampleField($value = 6);
$partage = New Posts();
$form = $this->createForm(PartagePostType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$partage = $form->getData();
$this->entityManager->persist($partage);
$this->entityManager->flush();
$this->addFlash('success', 'Votre post a bien été partagé');
}
return $this->render('home/index.html.twig', [
'posts' => $posts,
'tag' => $listTag,
'listPost' => $listPost,
'form' => $form->createView(),
]);
}
I dont' really get how you are trying to render you form but it doesn't work that way, in your modal_form.html.twig you should use the {{ form_start() }} and {{ form_end() }} twig helpers. They take in parameters the created view of the form, i.e, the variable "form" in your case (created in your render with the createView() method).
It should look like that:
{{ form_start(form}}
{{ form_row(form.field) }}
<input type="submit" value="submit">
{{ form_end(form) }}
"field" is whatever name you defined in your FormType. Notice how I added raw HTML for the submit button, it is suggested by Symfony you add the send button that way, even though you can add it in your FormType.
You can learn more about form rendering here : How to Customize Form Rendering
And forms in general there : Forms
Last thing, if you want to use multiple forms with this modal, don't forget to change the name of the variable (also don't forget to add this variable in your controller when you render a template with a form in it, obviously)

How to get formatted HTML generated by Symfony

I'm using Symfony2 to generate forms, or actually Twig, which uses Symfony's functions, so the view looks like this:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
This generates HTML code without any newlines or indentation. This is unreadable when I look into HTML source code.
Is there any way to force Symfony/Twig to format the generated HTML?
This link explains form customization in twig beautifully. There are numerous ways of applying css styling to form elements. For example, if you have a form with a field name you can add a css class to it this way:
{# render a widget, but add a "foo" class to it #}
{{ form_widget(form.name, {'attr': {'class': 'foo'}}) }}
or to the label:
{{ form_label(form.name, 'Your Name', {'label_attr': {'class': 'foo'}}) }}
Then you can use the css classes to render form elements as per your design. Hope you get the idea. The docs and link provided in the answer are both useful in this regard.
Update: the below "solution" made me a headache precisely this line:
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
It converts all non-ascii characters to entities, which is not very smart. Javascript's confirm and alert functions don't convert it back to UTF-8, they display strings as they are.
Thanks everybody, but I think I wasn't clear enough:) I didn't mean formatting by css or generally changing how the rendered page looks like, but rather changing HTML source code.
Anyway, with these two articles I finally managed to do what I wanted:
How do you format DOM structures in PHP?
http://php-and-symfony.matthiasnoback.nl/2011/10/symfony2-create-a-response-filter-and-set-extra-response-headers/
Step 1.
So, first the response listener, in (for example) AppBundle/EventListener/ResponseListener.php:
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class ResponseListener {
private $container;
public function __construct(Container $container) {
$this->container = $container;
}
function tidyHtml($html)
{
$dom = new \DOMDocument();
if (libxml_use_internal_errors(true) === true)
{
libxml_clear_errors();
}
$html = mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8');
$html = preg_replace(array('~\R~u', '~>[[:space:]]++<~m'), array("\n", '><'), $html);
if ((empty($html) !== true) && ($dom->loadHTML($html) === true))
{
$dom->formatOutput = true;
if (($html = $dom->saveXML($dom->documentElement, LIBXML_NOEMPTYTAG)) !== false)
{
$regex = array
(
'~' . preg_quote('<![CDATA[', '~') . '~' => '',
'~' . preg_quote(']]>', '~') . '~' => '',
'~></(?:area|base(?:font)?|br|col|command|embed|frame|hr|img|input|keygen|link|meta|param|source|track|wbr)>~' => ' />',
);
return '<!DOCTYPE html>' . "\n" . preg_replace(array_keys($regex), $regex, $html);
}
}
return false;
}
public function onKernelResponse(FilterResponseEvent $event) {
$request = $event->getRequest();
//only when format == html and environment == dev
if ($request->getRequestFormat() == 'html' && $this->container->get('kernel')->getEnvironment() == 'dev') {
$event->getResponse()->setContent($this->tidyHtml($event->getResponse()->getContent()));
}
}
}
Step 2.
In services.yml:
response_listener:
class: AppBundle\EventListener\ResponseListener
arguments: ['#service_container']
tags:
- { name: kernel.event_listener, event: kernel.response, method : onKernelResponse }

Form not valid in Symfony2

I am trying to process a form in Symfony2, I get all the values from it in the controller, but when I call:
$form->isValid()
it returns false. I am trying to process the form in a different Controller.
The form is rendered in two pieces, first some personal data and then some more information, but in the submit event of the form, I join all values serializing the forms. This is how I render the form in the view:
<form id="myform" action="{{ path('_process_my_form') }}" {{ form_enctype(form) }} method="POST">
{{ form_errors(form) }}
{{ form_widget(form._token) }}
{{ form_widget(form.first_name, {'attr': {'class': 'form-control'}} ) }}
... // then I render the rest of the personal information widgets
<button type="submit" class="btn btn-info btn-block">Submit</button>
</form>
<form id="myform2">
{{ form_widget(form.job_name, {'attr': {'class': 'form-control'}} ) }}
... // then I render the rest of the widgets (not personal information)
</form>
Then, in the Ajax request, I join the two forms like this:
$("#my_form").submit(function(e) {
e.preventDefault();
$.ajax({
type: e.target.method,
url: e.target.action,
data: $("#my_form").serialize() + $("#my_form2").serialize(),
beforeSend: function( xhr ) {},
success: function(data) {
//do something...
}
});
});
My _process_my_form rule looks like this:
_process_my_form:
pattern: /ajax/process-my-form
defaults: { _controller: MyBundle:User:processMyForm }
This is the Controller who controls the Ajax request:
public function processMyFormAction(Request $request)
{
if ($request->isMethod('POST'))
{
$myEntity = new myEntity();
$form = $this->container->get('form.factory')->create(new myFormType(), $myEntity);
$form->bind($request);
if ($form->isValid())
{
//Process the form... this code is never excecuted :(
}
}
}
Am I doing something wrong???
Thanks!!!
As of Symfony 2.3 I believe they changed the form handle from
$form->bind($request);
to
$form->handleRequest($request);
However I'm not sure if the former is still supported? As far as I can see, the bind method not longer exists in the Form Interface
You can read more here Symfony Cookbook - Form Direct Submit

Why getMethod() returns "GET" instead of "POST"?

The goal is to submit a POST form with two radiobuttons (tipo) and a text field (numero) to make a query in my DB and show the data to the user.
I am trying to submit the form below, however when I submit the form, the request coming accross is a 'GET REQUEST'. The form is in "SupuestoConfig.html.twig":
<div id="cuadro">
<form id="configurador" action="{{ path('configsup') }}" method="POST">
<p class="titulo_configurador">Elija supuesto penal:</p>
{{ form_row(form.tipo) }}
{{ form_row(form.numero, { 'label' : ' ', 'attr' : { 'class' : 'rec3' }}) }}
{{ form_rest(form) }}
<input type="submit" name="cargar" value="Cargar" class="inputbt"/>
</form>
</div>
I render the previous form in "principal.html.twig":
{{ render(controller('PprsBundle:Default:SupuestoConfig'), {'strategy': 'inline'}) }}
My "Controller.php":
/**
* #Route("/pprs/principal/supuesto={numero_supuesto}", name="configsup")
* #Template("PprsBundle:Default:SupuestoConfig.html.twig")
*/
public function SupuestoConfigAction($numero_supuesto = null)
{
$form = $this->createFormBuilder(null)
->add('tipo', 'choice', array(
'choices' => array(
'aleatorio' => 'Aleatorio',
'pornumero' => 'Por número'),
'multiple' => false,
'expanded' => true,
'data' => 'aleatorio'
))
// This add may contains error
->add('numero', 'text', array('label' => ' ','disabled' => true))
->getForm();
$peticion = $this->getRequest();
echo ('<script type="text/javascript">alert ("'.$peticion->getMethod().'");</script>');// Returns 'GET'
if ($peticion->isMethod('POST')) {
// Symfony2.2
$form->bind($peticion);
**$datos = $form->getData();**
*//foreach(array_keys($datos) as $p) {
//echo ('<script type="text/javascript">alert ("'.$datos.'");</script>');
//}*
if ($form->isValid()) { ... }
In Controller.php, despite I´ve got a GET request (when I remove the line
->add('numero', 'text',..
I´ve got a POST request, why is that?), in getData I don´t get the text field.
Finally, my routing.yml:
pprs_principal:
pattern: /pprs/principal/supuesto={numero_supuesto}/
defaults: { _controller: PprsBundle:Default:principal, numero_supuesto: 1 }
_pprs_principal:
pattern: /pprs/principal/
defaults: { _controller: FrameworkBundle:Redirect:redirect, route: pprs_principal }
Sorry for my bad english, Thanks in advance
Edit:
1) Anybody knows why I obtain a GET request instead of a POST when I add the text field in my createFormBuilder?
2) Anybody knows why Don't I get the text field when I call getData?
Help me please...
Maybe this answer could help you out:
getRequest() returns "GET" when posting form
Basically, when rendering a form with a {% render %} tag, it actually creates "another" request... It doesn't pass in the locale, the method, etc.
I opened a bug about this, and it went as By Design:
https://github.com/symfony/symfony/issues/7551

How to load a controller function and render it in a twig tag using Symfony2?

I am using Symfony2 and Twig. I have a function (below) in my controller that returns a specific text. Is it possible to call that function directly from my template and change the {{text}} in my template to whatever the function returns, possibly via Ajax?
Here's my function:
public function generateCode($url) {
$url = $_SERVER['SERVER_NAME'] . '/embed/' . $url;
$return = '<iframe>'.$url.'</iframe>';
return $return;
}
Another controller function calls the function above and renders my template:
public function getCodeAction($url) {
$text = $this->generateCode($url);
return $this->render('MyMyBundle:User:code.html.twig', array('text' => $text));
}
In my template I am using:
{{ text }}
to display the value.
In Symfony 2.2, this was changed.
The render tag signature and arguments changed.
Before:
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, { 'alt': BlogBundle:Post:error' } %}
After:
{% render controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
or
{{ render(controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error'}) }}
Note: The function is the preferred way.
See https://github.com/symfony/symfony/blob/2.2/UPGRADE-2.2.md
You can use ajax if you have dynamic data, but as far as I can see from your brief info, you can always execute that controller function directly from your view:
{% render "MyMyBundle:User:generateCode" with { 'url': 'your url here' } %}
More Information on this available at:
http://symfony.com/doc/2.0/quick_tour/the_view.html, under Embedding other Controllers
For the record, in new versions you need to use the absolute URL:
{{ render url('my_route_id', {'param': value}) }}
{{ render(controller("AcmeDemoBundle:Demo:topArticles", {'num': 10})) }}
In Silex I solved it like this:
{{ render(url('route_name', {'param': value})) }}
If you do not have the route name, URL can be used:
{{ render(app.request.baseUrl ~ '/some-path/' ~ value) }}
If using URL we should always concat the baseUrl.
Symfony 2.6+
in twig:
{{ render(controller('AppBundle:PropertySearch:featuredProperties', {'limit': 15})) }}
controller:
/**
* featuredPropertiesAction
*
* #param Request $request
* #param int $limit
*
* #return Response
*/
public function featuredPropertiesAction(Request $request, $limit)
{
$search = $this->resultsHelper->featuredSearch($limit);
return $this->render('HASearchBundle::featured_properties.html.twig', [
'search' => $search,
]);
}

Resources