Description
I have a problem that error messages for an embedded form are bubbling to the parent form when used with another embedded form pointing to the same property_path of a related object.
My situation is like this, I have Users and Account entities I have split up the Account into different forms, then for the registration form I am pulling these bits together like so:
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', 'email', array(
'label' => '* Email address:'
))
->add('account_personal', 'my_personalinfo_form', array(
'property_path' => 'account'
))
->add('account_contact', 'my_contactinfo_form', array(
'property_path' => 'account'
))
;
}
The problem is that error messages for account_personal
are bubbling to the top of the form. For example "Please enter your first name" if first name is left blank in the personal info form. The 'personal' and 'contact' forms work fine in their own forms on their own pages.
The error messages for account_contact are fine and appear next to the correct fields.
HOWEVER, if I swap the two ->add
bits about above (so have account_contact
first) then the problem reverses; the error messages for account_personal
now appear correctly next to their corresponding fields, but now the errors for account_contact
get bubbled to the top!
Does this sound like a bug or am I doing something wrong?
Thanks!
---- Other files for reference:
Personal info form:
class PersonalInfoType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', 'text')
->add('first_name', 'text', array(
'required' => true,
'label' => '* First name:'
))
->add('last_name', 'text', array(
'required' => true,
'label' => '* Surname:'
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'My\UserBundle\Entity\Account',
'validation_groups' => array('personalInfo')
));
}
public function getName()
{
return 'my_personalinfo_form';
}
Contact info form:
class ContactInfoType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('postcode', 'text', array(
'required' => true
))
->add('address_1', 'text', array(
'required' => true
))
->add('address_2', 'text', array(
'required' => false
))
->add('address_3', 'text', array(
'required' => false
))
->add('town', 'text')
->add('phone_daytime', 'text', array(
'required' => true
))
->add('phone_mobile', 'text', array(
'required' => true
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'My\UserBundle\Entity\Account',
'validation_groups' => array('contactInfo')
));
}
public function getName()
{
return 'my_contactinfo_form';
}
and the Account entity for completion:
/**
* My\UserBundle\Entity\Account
*
* @ORM\Entity
* @ORM\Table( name="accounts" )
*/
class Account
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="string", length=25, nullable=true)
* @Assert\Choice(choices = {"Mr", "Mrs", "Miss", "Ms", "Dr", "Prof"}, message = "Choose a valid title", groups={"personalInfo"})
*/
protected $title;
/**
* @ORM\Column(type="string", length=150, nullable=true)
* @Assert\NotBlank(message="Please enter your first name", groups={"personalInfo"})
* @Assert\Length(max=150, maxMessage="null|Your first name must have less than {{ limit }} characters", groups={"personalInfo"})
* @Assert\Regex(
* pattern="/\d/",
* match=false,
* message="Your name cannot contain a number"
* )
*/
protected $first_name;
/**
* @ORM\Column(type="string", length=150, nullable=true)
* @Assert\NotBlank(message="Please enter your last name", groups={"personalInfo"})
* @Assert\Length(max=150, maxMessage="null|Your last name must have less than {{ limit }} characters", groups={"personalInfo"})
* @Assert\Regex(
* pattern="/\d/",
* match=false,
* message="Your name cannot contain a number"
* )
*/
protected $last_name;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @MyAssert\Phone(message="Your daytime phone number is not valid", groups={"contactInfo"})
*/
protected $phone_daytime;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @MyAssert\MobilePhone(message="Your mobile phone number is not valid", groups={"contactInfo"})
*/
protected $phone_mobile;
/**
* @ORM\Column(type="string", length=255)
* @Assert\NotBlank(message="Please enter the first line of your address", groups={"contactInfo"}
* @Assert\Length(max=250, maxMessage="null|The first line of your address must have less than {{ limit }} characters", groups={"contactInfo"})
*/
protected $address_1;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Assert\Length(max=250, maxMessage="null|The second line of your address must have less than {{ limit }} characters", groups={"contactInfo"})
*/
protected $address_2;
/**
* @ORM\Column(type="string", length=255, nullable=true)
* @Assert\Length(max=250, maxMessage="null|The third line of your address must have less than {{ limit }} characters", groups={"contactInfo"})
*/
protected $address_3;
/**
* @ORM\Column(type="string", length=45, nullable=true)
* @Assert\NotBlank(message="Please enter your town", groups={"contactInfo"})
* @Assert\Length(max=45, maxMessage="null|Your town name must have less than {{ limit }} characters", groups={"contactInfo"})
*/
protected $town;
/**
* @ORM\Column(type="string", length=45, nullable=true)
* @Assert\NotBlank(message="Please enter your postcode", groups={"contactInfo"})
* @MyAssert\Postcode(message="Invalid postcode entered", groups={"contactInfo"})
*/
protected $postcode;
... etc