目前我在表单中嵌入了实体表单。我想基础数据在用户选择项目时自动填充地址字段。但是,如下所示,在实体和Symfony 2文档中指定的相应ajax代码中使用表单事件,地址字段永远不会填充在相应的ajax响应中。
使用var_dump我可以看到,当我添加地址字段时,地址被抓取并发送到数据选项。但是,当表单仅与所选项目一起提交时,它永远不会出现在表单响应中。
这是正确的方法,还是我错过了某个重要的部分?或者symfony不这样做,我应该通过jquery / ajax吗?
TransactionUser
class TransactionUser
{
/**
* @var string
*
* @ORM\Column(name="id", type="guid")
* @ORM\Id
*/
private $id;
/**
* The associated transaction to this TransactionUser.
*
* @var \Acme\BaseBundle\Entity\Transaction $transaction
*
* @ORM\ManyToOne(targetEntity="Acme\BaseBundle\Entity\Transaction", inversedBy="transactionUsers", cascade={"all"})
*/
private $transaction;
/**
* The Project that this TransactionUser is associated with.
*
* @var \Acme\BaseBundle\Entity\Project
*
* @ORM\ManyToOne(targetEntity="Acme\BaseBundle\Entity\Project", inversedBy="transactionUsers", cascade={"all"})
*/
private $project;
}
交易
class Transaction
{
/**
* @var string
*
* @ORM\Column(name="id", type="guid")
* @ORM\Id
*/
private $id;
/**
* @var \Acme\BaseBundle\Entity\Address
*
* @ORM\ManyToOne(targetEntity="Acme\BaseBundle\Entity\Address", cascade={"persist"}, inversedBy="propertyAddressTransactions")
*/
private $propertyAddress;
/**
* @ORM\OneToMany(targetEntity="Acme\BaseBundle\Entity\TransactionUser", mappedBy="transaction", cascade={"all"})
*/
private $transactionUsers;
}
地址
class Address
{
/**
* The database id for the Address.
*
* @var string
*
* @ORM\Column(name="id", type="guid")
* @ORM\Id
*/
private $id;
/**
* The first line of the street address.
*
* @var string
*
* @ORM\Column(name="streetAddressLine1", type="text")
*/
private $streetAddressLine1;
/**
* The Transactions that list this address as the property address.
*
* @ORM\OneToMany(targetEntity="Acme\BaseBundle\Entity\Transaction", mappedBy="propertyAddress")
*/
private $propertyAddressTransactions;
}
项目
class Project
{
/**
* @var string
*
* @ORM\Column(name="id", type="guid")
* @ORM\Id
*/
private $id;
/**
* @ORM\OneToMany(targetEntity="Acme\BaseBundle\Entity\TransactionUser", mappedBy="project", cascade={"all"})
* \Doctrine\Common\Collections\ArrayCollection
*/
private $transactionUsers;
}
NewTransactionFormType
class NewTransactionFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('project', EntityType::class, array(
'class' => 'AcmeBaseBundle:Project',
'required' => false,
'optional' => true,
'label' => 'Select Project',
'placeholder' => 'Select Project',
'property' => 'projectName',
'query_builder' => function (EntityRepository $er) {
$queryBuilder = $er->createQueryBuilder('p');
return $queryBuilder;
},
));
$builder->add('transaction', NewTransactionSubFormType::class);
$builder->get('transaction')->add('propertyAddress', AddressFormType::class);
//Listeners on project to set the address
$formModifier = function (FormInterface $form, Project $project = null) {
$address = null;
if (!is_null($project) && !is_null($project->getId())) {
$address = $project->getFirstTransactionAddress();
}
$form->get('transaction')->add('propertyAddress', AddressFormType::class, array(
'data' => $address
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. Transaction
$data = $event->getData();
$formModifier($event->getForm(), $data->getProject());
}
);
$builder->get('project')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$project = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $project);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\TransactionUser',
));
}
}
NewTransactionSubFormType
class NewTransactionSubFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', TextType::class, array(
'label' => 'Name',
'attr' => array(
'class' => '',
'placeholder' => 'Name',
),
'required' => true,
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\Transaction',
));
}
}
AddressFormType
class AddressFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('streetAddressLine1', TextType::class, array(
'label' => 'Street Address Line 1',
'attr' => array(
'class' => '',
'placeholder' => 'Street Address Line 1',
),
'required' => true,
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\BaseBundle\Entity\Address',
));
}
}