Form not valid in Symfony2 - symfony

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

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)

Symfony 3 : password validation

I use this code to validate user password :
$encoderService = $this->container->get('security.password_encoder');
$match = $encoderService->isPasswordValid($user, $request->query->get('password'));
but it always returns 'false' even the password is correct
You're using the password encoder in the wrong way... Check Symfony doc on security
Here is an example on how to use it.
app/config/security.yml
security:
encoders:
AppBundle\Entity\Security:
algorithm: bcrypt
src/AppBundle/Controller/SecurityController.php
class SecurityController extends Controller {
private $tokenManager;
private $encoder;
public function __construct(CsrfTokenManagerInterface $tokenManager=null, UserPasswordEncoderInterface $encoder) {
$this->tokenManager=$tokenManager;
$this->encoder=$encoder;
}
**[...]**
public function editAction(Security $user) {
if($user->getOldPassword() !== null && $user->getPlainPassword() !== null && $this->encoder->isPasswordValid($user, $user->getOldPassword())) {
$user->setPassword($this->encoder->encodePassword($user, $user->getPlainPassword()));
$em->flush();
}
}
}
Form view
<form action="{{ form.vars.action }}" method="{{ form.vars.method }}" onsubmit="event.preventDefault(); ajaxSubmit($(this));">
<div class="form-section-title">Change password</div>
<div class="form-col-2">
<div class="input-field">
{{ form_label(form.oldPassword, 'Current password') }}
{{ form_widget(form.oldPassword, { 'attr': {'autocomplete': 'off' }}) }}
</div>
<div class="input-field">
</div>
</div>
<div class="form-col-2">
<div class="input-field">
{{ form_label(form.plainPassword.first, 'New password') }}
{{ form_widget(form.plainPassword.first, { 'attr': {'autocomplete': 'off' }}) }}
</div>
<div class="input-field">
{{ form_label(form.plainPassword.second, 'Repeat new password) }}
{{ form_widget(form.plainPassword.second, { 'attr': {'autocomplete': 'off' }}) }}
</div>
</div>
<input name="{{ form._token.vars.full_name }}" type="hidden" value="{{ form._token.vars.value }}">
<div class="input-field submit-container">
<button class="waves-effect waves-light btn btn-2 close_action">Annuler</button>
<button class="waves-effect waves-light btn btn-1" type="submit">Valider</button>
</div>
</form>
Javascript submit function
function ajaxSubmit(node) {
$.ajax({
type: node.attr("method"),
url: node.attr("action"),
enctype: 'multipart/form-data',
data: new FormData(node[0]),
processData: false,
contentType: false,
cache: false
}).done(function(response, status, xhr) {
//Your code here
}).fail(function(request, status, error) {
console.error(request);
console.error(status);
console.error(error);
});
}
Side note: Should be obvious, but you should use POST and not GET with your AJAX query.
First because GET parameters are as clear as day... It's quite dangerous for a password to be changed like that.
Second because, as soon as your site will be in HTTPS, your POST parameters will be encrypted. Making it really hard to read the content for anyone sniffing around.
And last, avoid to post code in comments, edit your question instead... ;)

How to reload part of twig with ajax

I need to reload part of my html.twig:
in controller:
$entity = $em->getRepository('PublishDemandsBundle:Demands')->find($id);
In twig:
{% for n in entity %} {{ n.Id }} {% endfor %}.
i need how to reload $entity with ajax.Can someone help me and thanks.
You can do this with jQuery. I think the best way to do this (I think) is to have a method in your controller that do nothing but a findAll() on your Demands repo :
public function demandsAction()
{
$entity = $em->getRepository('PublishDemandsBundle:Demands')->findAll();
return $this->render('PublishDemandsBundle:Demands:liste.html.twig', array(
'entity' => $entity
));
}
Make sure this Action can be called by a route, let's say /ajax/demands/
Then, in your twig template, just do :
<div id="demands">
{{ render(controller("PublishDemandsBundle:MainController:demands")) }}
</div>
reload
With a bit of jQuery :
$('#reload').click(function() {
$.get("/ajax/demands", function( data ) {
$('#demands').html( data );
});
I haven't tested this yet, and it might be adapted to your case, but again, I would do it this way.

symfony2 form is not displaying

I am learning symfony2 and i have created one form in controller which is as bellow.
the controller file as DefaultController.php
namespace Banner\TestBundle\Controller;
use Banner\TestBundle\Entity\Contact;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Banner\TestBundle\Entity\Task;
use Symfony\Components\HttpFoundation\Request;
class DefaultController extends Controller
{
public function newAction(Request $request)
{
echo "The controller is called ";
$task = new Task();
$task->setTask("Write a blog Post ");
$task->setDueDate(new DateTime('tomorrow'));
$form = $this->createFormBuilder($task)
->add('task','text ')
->add('duedate','date')
->getForm();
return $this->render('BannerTestBundle:default:zoo.html.twig',array('form'=>$form->createView()));
}
}
my routing file is as below.
routing.yml
task_new:
pattern: /task/{request}
defaults: { _controller: BannerTestBundle:Default:new}
and the zoo.html.twig file is as bellow.
{% extends '::page.html.twig' %}
{% block title %}The Zoo{% endblock %}
{% block content %}
<form action="{{ path('task_new') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit">
</form>
{% endblock %}
as i am passing the "task/GET" in my url it will shows the 'Request does not exist. error 500'.
what i basically want to do is when i pass the url the zoo.html.twig will be called. i want to display the form in zoo.html.twig.
You don't need to pass $request to your action and you don't need to put it in your route. The request object is available in global context. So
task_new:
pattern: /task-new
defaults: { _controller: BannerTestBundle:Default:new}
You can either leave it this way
public function newAction(Request $request)
or have
public function newAction()
and access request object like this
$request = $this->getRequest();
Your routing file is not properly indented so the yaml will not parse properly. Try:
task_new:
pattern: /task/{request}
defaults: { _controller: BannerTestBundle:Default:new}
Also:
It is probably a bad idea to override request that way
You don't appear to be doing anything with request in your controller

Form does not display form errors in template

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.

Resources