Symfony2 interaction between forms, problems if validation fails - forms

I have 2 forms which display the following:
They are created dynamically, not from entities.
My controller is the following:
<?php
...create the relevant array $rolesListForForm
$form = $this->createFormBuilder()->getForm(); //create empty form
$HRsInThisProject = $em->getRepository('AppBundle:User')->findUsersByProject($prj);
foreach ($HRsInThisProject as $key => $HR)
{
$form->add('roleOf_'.$key, 'choice', array('choices' => $rolesListForForm, 'required' => true, 'data' => $HR['role'], 'label' => false, ));
$form->add('isActive_'.$key, 'choice', array('choices' => [0 => 'Inactive', 1 => 'Active'] , 'required' => true, 'data' => $HR['is_active'], 'label' => false, ));
}
...create the relevant array $HRsInMyDomainForForm
$form->add('showinactive', 'checkbox', array('label' => 'Show inactive users', 'required' => false, 'data' => true, ));
$form->add('HRid', 'choice', array('choices' => $HRsInMyDomainForForm,'required' => false, 'placeholder' => 'Choose a resource', 'label' => false, ));
$form->add('role', 'choice', array('choices' => $rolesListForForm,'required' => false, 'placeholder' => 'Choose a role', 'label' => false, ));
$form->add('save', 'submit', array('label' => 'Save'));
$form->handleRequest($request);
// If form is valid
if ($form->isValid())
{
...lots of logic here to understand if persisting or not stuff on DB, then I simply refresh the current page
return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $prj->getId())));
}
//creation of the second form
$formGlobalSearch=$this->createFormBuilder()
->add('username', 'text', array('constraints' => new UsernameExists()))
->add('role', 'choice', array('choices' => $rolesListForForm,'required' => false, 'placeholder' => 'Choose a role', 'label' => false, ))
->add('submitUsername', 'submit', array('label' => 'Search username globally'))
->getForm();
$formGlobalSearch->handleRequest($request);
if ($formGlobalSearch->isValid())
{
//persist stuff on DB and refresh current page
return $this->redirect($this->generateUrl('hr_manage', array('projectID' => $prj->getId())));
}
return $this->render('HR/show.html.twig', array('projectID' => $prj->getId(), 'hrlist' => $HRsInMyDomain, 'form' => $form->createView(), 'HRs' => $HRsInThisProject, 'formGlobalSearch' => $formGlobalSearch->createView(),));
It all works smoothly, the only problem occurs when the second form throws a validation error. When it does the top form is not properly rendered anymore, I see stuff like this:
Here is the relevant part of the twig:
{{ form_start(form) }}
{{ form_row(form.showinactive) }}
<table>
<tr>
<td>User ID</td>
<td>Name</td>
<td>Role</td>
<td>Started</td>
<td>Status</td>
</tr>
{% for key, HR in HRs %}
<tr>
<td>{{ key }}</td>
<td>{{ HR.name }}</td>
<td>{{ form_row(form['roleOf_' ~ key]) }}</td>
<td>{{ HR.started_at|date('Y-m-d H:i:s') }}</td>
<td>{{ form_row(form['isActive_' ~ key]) }}</td>
</tr>
{% endfor %}
</table>
<br>
Add new resource:
{{ form_row(form.HRid) }}{{ form_row(form.role) }}
{{ form_row(form.save) }}
{{ form_end(form) }}
<br>
Or you can search for a user of ProJacked at global level
{{ form_start(formGlobalSearch) }}
{{ form_errors(formGlobalSearch) }}
{{ form_widget(formGlobalSearch) }}
{{ form_end(formGlobalSearch) }}
Any idea?

Related

How can I create an "update" form in Symfony 4?

With this form I want to update my database entry:
myController.php
public function index($id, $slug, Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$item = new User();
$item= $this->getDoctrine()->getRepository(User::class)->find($id);
$form = $this->createFormBuilder($item)
->add('username', TextType::class, array('attr' => array('class' => 'form-control')))
->add('email', EmailType::class, array('attr' => array('class' => 'form-control')))
->add('is_active', HiddenType::class)
->add('plainPassword', RepeatedType::class, array('type' => PasswordType::class,'invalid_message' => 'The password fields must match.','options' => array('attr' => array('class' => 'password-field')),'required' => true,'first_options' => array('label' => 'Passwort', 'attr' => array('class' => 'form-control')),'second_options' => array('label' => 'Passwort wiederholen', 'attr' => array('class' => 'form-control')),))
->add('cancel', ButtonType::class, array('label' => 'Cancel','attr' => array('class' => 'cancel form-btn btn btn-default pull-right close_sidebar close_h')))
->add('update', SubmitType::class, array('label' => 'Update','attr' => array('class' => 'form-btn btn btn-info pull-right','style' => 'margin-right:5px')))
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->flush();
return $this->redirectToRoute('pages', array(
'slug' => $slug,
));
}
return $this->render('form.html.twig', ['form' => $form->createView()]);
}
form.html.twig:
{{ form_start(form) }}
<div>
{{ form_label(form.username) }}
{{ form_widget(form.username) }}
{{ form_errors(form.username) }}
{{ form_help(form.username) }}
</div>
<div>
{{ form_label(form.email) }}
{{ form_widget(form.email) }}
{{ form_errors(form.email) }}
{{ form_help(form.email) }}
</div>
<div>
{{ form_widget(form.is_active) }}
{{ form_errors(form.is_active) }}
{{ form_help(form.is_active) }}
</div>
<div>
{{ form_label(form.plainPassword.first) }}
{{ form_widget(form.plainPassword.first) }}
<div class="text-red">{{ form_errors(form.plainPassword.first) }}</div>
{{ form_help(form.plainPassword.first) }}
</div>
<div>
{{ form_label(form.plainPassword.second) }}
{{ form_widget(form.plainPassword.second) }}
<div class="text-red">{{ form_errors(form.plainPassword.second) }}</div>
{{ form_help(form.plainPassword.second) }}
</div>
{{ form_end(form) }}
But when I edit for example the username in my form and I click on "Update" then I get the error message
An exception occurred while executing 'INSERT INTO members (username,
password, email, is_active) VALUES (?, ?, ?, ?)' with params ["cat2",
"123", "cat#cat.de", "1"]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
'cat#cat.de' for key 'UNIQ_12A0D2FFE7927C74'
I actually expect the SQL make an UPDATE instead of INSERT...
You need to load the User from the UserRepository::find($id)
use App\Repository\UserRepository;
// ...
class MyController
{
public function index($id, $slug,
Request $request,
UserPasswordEncoderInterface $passwordEncoder,
UserRepository $userRepository)
{
$item = $userRepository->find($id);
if(NULL === $item) {
throw $this->createNotFoundException('could not find this user.');
}
$form = $this->createFormBuilder($item)
// ...
}
// ...
}

Symfony4 Form not submitted

I have a problem with my Form in symfony4, when I click on the submit button it is not submitted (It doesn't pass the isSubmitted condition)
Here is my Form
<?php
namespace App\Form\Backend\Team;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
/**
* Class AddTeamForm
* #package App\Form\Backend\Team
*/
class TeamForm extends AbstractType
{
const NAME = 'name';
const WEBSITE = 'website';
const IRC = 'irc';
const DISCORD = 'discord';
const TWITTER = 'twitter';
const FACEBOOK = 'facebook';
const HIDDEN = 'hidden';
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', HiddenType::class)
->add(self::NAME, TextType::class, [
'required' => true,
'label' => 'admin.team.form.name'
])
->add(self::WEBSITE, TextType::class, [
'required' => false,
'label' => 'admin.team.form.website'
])
->add(self::IRC, TextType::class, [
'required' => false,
'label' => 'admin.team.form.irc'
])
->add(self::DISCORD, TextType::class, [
'required' => false,
'label' => 'admin.team.form.discord'
])
->add(self::TWITTER, TextType::class, [
'required' => false,
'label' => 'admin.team.form.twitter'
])
->add(self::FACEBOOK, TextType::class, [
'required' => false,
'label' => 'admin.team.form.facebook'
])
->add(self::HIDDEN, CheckboxType::class, [
'required' => false,
'label' => 'admin.team.form.hidden'
]);
}
}
and Here is my action
/**
* #Route("/add", name="add")
*/
public function add(Request $request)
{
$form = $this->createForm(TeamForm::class);
$form->handleRequest($request);
if ($form->isSubmitted()) {
var_dump('submitted');
if($form->isValid())
{
} else {
var_dump('non vlide');exit;
}
$team = $form->getData();
}
return $this->render('backend/team/add.html.twig', [
'form' => $form->createView(),
]);
}
and my view
{{ form_start(form, {attr: {class: 'ui form inverted', novalidate:'novalidate', 'action': url('admin_team_add')} }) }}
{{ form_errors(form) }}
<div class="ui grid two column">
<div class="row">
<div class="twelve wide column">
{{ form_row(form.name) }}
{{ form_row(form.website) }}
{{ form_row(form.irc) }}
{{ form_row(form.discord) }}
{{ form_row(form.twitter) }}
{{ form_row(form.facebook) }}
<div class="field">
<div class="ui checkbox">
{{ form_widget(form.hidden) }}
{{ form_label(form.hidden) }}
{{ form_errors(form.hidden) }}
</div>
</div>
<input type="submit" class="ui button green" value="{{ 'admin.team.form.btn-create' }}"/>
</div>
</div>
</div>
{{ form_end(form) }}
Like I said, When I click my submit button, the var_dump 'submitted' is not shown. The page refreshes but nothing happen, like a normal page refresh.
I must miss something but can't figure what ...
you can check if your route name exist:
php bin/console debug:router admin_team_add
if it's not exist , change your view action to :
{{ form_start(form, {attr: {class: 'ui form inverted', novalidate:'novalidate', 'action': url('add')} }) }}
or change your controller route name to :
/**
* #Route("/add", name="admin_team_add")
*/
public function add(Request $request)
{

Symfony submit button doesn't flush/update the entity properly

My entity "corporation" has two ManyToMany relationships with
entity "User" and
entity "Agency"
The related data, I'd like to display as a table with a EntityType-dropdown to (un-)select data.
Therefor I have the following form:
$builder
->add('usercorporations', EntityType::class, array(
'class' => 'UserBundle:User',
'query_builder' => function (EntityRepository $er) use ($corporationMarket) {
return $er->createQueryBuilder('e')
->andWhere(':marketIds MEMBER OF e.markets')
->setParameter('marketIds',$corporationMarket)
->orderBy('e.lastName', 'ASC');
},
'choice_label' => function($user) {
return $user->getFirstName() . ' ' . $user->getLastName() ;
},
'expanded' => false, 'multiple' => true,
'required'=>false,
'by_reference' => false,
'empty_value' => "label.select_user",
'translation_domain' => 'Agency'))
->add('agencies', EntityType::class, array(
'class' => 'AppBundle:Agency',
'query_builder' => function (EntityRepository $er){
return $er->createQueryBuilder('a')
->addOrderBy('a.account', 'ASC');
},
'label' => 'label.agencies',
'choice_label' => function($agency) {
return $agency->getId() . ' - ' . $agency->getAccount() . ' - ' . $agency->getCityName() . ', ' . $agency->getState();
},
'expanded' => false, 'multiple' => true,
'required' => false,
'translation_domain' => 'Agency',
));
my twig template includes the two dropdowns as well as two tables for each of the entities.
{{ form_start(form) }}
{# This renders a red banner if the form contains errors.
If the form variable is not called "form", pass it explicitly. #}
{% include 'Form/form_errors_banner.html.twig' %}
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.assignedUsers'|trans }}</legend>
{{ form_widget(form.usercorporations) }}
<br>
<br>
{% include 'UserBundle:User:AssignedUsers.html.twig' %}
</div>
</div>
</div>
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.assignedAgencies'|trans }}</legend>
{{ form_widget(form.agencies) }}
<br>
<br>
{% include 'AppBundle:Agency:AssignedAgencies.html.twig' with {'entity': corporation} %}
</div>
</div>
</div>
<div>
<input type="submit" class="btn-primary btn" value="{{ 'label.apply'|trans }}"/>
</div>
{{ form_end(form) }}
</div>
I'm using the tables (AssignedUsers and AssignedAgencies) on other pages too, that's all working fine.
So now my problem:
I'd like to have the possibility to simply add and remove users or agencies. By just deselecting e.g. a user from the dropdown and then submitting, it's working, the user isn't assigned to the corporation anymore. Somehow, the same procedure is not working for the agencies. I don't know why though, I dumped the data prior to and after the flush and it's dumping the correct data, but when I return to the corporation, nothing changed.
My controller action:
/**
* #Route("/corporation/{id}/{page}", name="appBundle_corporation", requirements={"id" = "\d+", "page" = "\d+"}, defaults={"page" = 1}))
*/
public function corporationAction($id, Request $request, $page)
{
$repository = $this->getDoctrine()
->getRepository('AppBundle:Corporation');
$em = $this->getDoctrine ()->getManager ();
$corporation = $repository->findOneById($id);
/*
* CREATE PAGINATION FOR TABLES
*/
//assigned Users
$assignedUsers = $corporation->getUsercorporations();
$assignedAgencies = $corporation->getAgencies();
dump($assignedAgencies);
$form = $this->createForm(CorporationAssignmentType::class,$corporation, array(
'corporationMarket' => $corporationMarket,
));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($corporation);
$em->flush();
dump($assignedAgencies);
$this->addFlash(
'success',
'Your changes were saved!'
);
return $this->redirectToRoute('appBundle_corporation', array('id' => $corporation->getId()));
}
return $this->render('AppBundle::corporation.html.twig', array(
'item' => $corporation,
'corporation'=>$corporation,
'assignedUsers'=>$userTable,
'assignedAgencies' => $agencyTable,
'form' => $form->createView(),
));
}
any ideas why it's flushing the users but not the agencies?
I solved my problem that way, but it might be that #ASOlivieri 's answer could've helped es well.
What I did initially is:
in Entity Agency
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Corporation", inversedBy="agencies", cascade={"persist"})
* #ORM\JoinTable(name="app_agency_corporations",
* joinColumns={#ORM\JoinColumn(name="agency_id", referencedColumnName="iata8")},
* inverseJoinColumns={#ORM\JoinColumn(name="corporation_id", referencedColumnName="ucid")})
* #var \AppBundle\Entity\Corporation
**/
private $corporations;
in Entity Corporation
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\Agency", mappedBy="corporations")
**/
private $agencies;
when switching it --> the shorter code to the Agency's property corporations and the longer code about the JoinTable etc. to the Corporation's property agencies it worked.
If anybody could explain to me why this is the solution, I'd be happy!
If your entities work in other places (other controllers, etc.) then I suspect you have to by_reference to false in your agencies form options.
->add('agencies', EntityType::class, array(
'class' => 'AppBundle:Agency',
'query_builder' => function (EntityRepository $er){
return $er->createQueryBuilder('a')
->addOrderBy('a.account', 'ASC');
},
'label' => 'label.agencies',
'choice_label' => function($agency) {
return $agency->getId() . ' - ' . $agency->getAccount() . ' - ' . $agency->getCityName() . ', ' . $agency->getState();
},
'expanded' => false, 'multiple' => true,
'required' => false,
'by_reference' => false,
'translation_domain' => 'Agency',
));
It looks as though it's set that way in your user form options.

Display errors message form

i am trying to show errors messages at the top on page in my twig view but {{ Form_errors(form)}} don't display password errors! but shows other errors..
Form builder
->add('password', RepeatedType::class, array(
'type' => PasswordType::class,
'options' => array('attr' => array('class' => 'password-field')),
'required' => true,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password').
view :
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
{{ form_widget(form) }}`enter code here`
{{dump(form_errors(form))}}
<input type="submit" value="Create" />
{{ form_end(form) }}
try
{{dump(form_errors(form.password))}}
to display errors specific to the password field

Double textarea? Symfony 2 with FOSU

i have this weird problem, and i really dont know why this happens.
The text areas are doubled and their position is bad.
Look at the image.
So, the builder looks like:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('imie', 'text', array('label' => false, 'translation_domain' => 'FOSUserBundle'))
->add('nazwisko', 'text', array('label' => false, 'translation_domain' => 'FOSUserBundle'))
->add('username', null, array('label' => false, 'translation_domain' => 'FOSUserBundle'))
->add('email', 'email', array('label' => false, 'translation_domain' => 'FOSUserBundle'))
->add('telefon', 'number', array('label' => false, 'translation_domain' => 'FOSUserBundle'))
->add('plainPassword', 'repeated', array(
'type' => 'password',
'options' => array('translation_domain' => 'FOSUserBundle'),
'first_options' => array('label' => false),
'second_options' => array('label' => false),
'invalid_message' => 'fos_user.password.mismatch',
))
->add('captcha', 'captcha', array(
'label' => ' ',
'width' => 200,
'height' => 50,
'length' => 6,
'invalid_message' => 'The captcha code is invalid.'
))
;
}
and the html.twig
http://pastebin.com/2pbHqNyH
Note that im using symfony with twig for 2 weeks and im begginer. And im also new to the FOSU. I just want to change the default look of register form from FOSU to suitable for my site.
That is because your repeated password contains 2 fields, so the plainPassword field rendering contains invalid css structure.
Replace:
<div class="form-group">
{{ form_label(form.plainPassword, 'Hasło:', {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
<div class="col-sm-5">
{{ form_widget(form.plainPassword, {'attr': {'class':'form-control' }}) }}
{{ form_errors(form.plainPassword) }}
</div>
</div>
By:
<div class="form-group">
{{ form_label(form.plainPassword.first, 'Hasło:', {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
<div class="col-sm-5">
{{ form_widget(form.plainPassword.first, {'attr': {'class':'form-control' }}) }}
{{ form_errors(form.plainPassword.first) }}
</div>
</div>
<div class="form-group">
{{ form_label(form.plainPassword.second, 'Hasło:', {'label_attr': {'class': 'col-sm-3 control-label'}}) }}
<div class="col-sm-5">
{{ form_widget(form.plainPassword.second, {'attr': {'class':'form-control' }}) }}
{{ form_errors(form.plainPassword.second) }}
</div>
</div>
More details: http://symfony.com/doc/current/reference/forms/types/repeated.html