Tôi gần như đã có nó. Nếu bất cứ ai bao giờ cần ở đây là những gì cần phải được thêm vào làm cho công việc giải pháp này một cách hoàn hảo khi chỉnh sửa một mục hiện có:
class ItemDetailForm extends AbstractType
{
...
$builder->addEventListener(FormEvents::POST_SET_DATA, function (DataEvent $event) use ($refreshTopic) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
$form->get('region')->setData($data->getCity()->getRegion());
});
}
Chỉnh sửa: kể từ symfony 2.1, sự kiện POST_SET_DATA được gọi trước khi trẻ em được thêm vào biểu mẫu , gây ra tất cả các get ('khu vực') để nâng cao một ngoại lệ. Giải pháp là tạo ra lĩnh vực này trong POST_SET_DATA và không nằm trong buildForm():
/** @var FormFactory $factory */
$form->add($factory->createNamed('region', 'entity', null, array(
'class'=>'AcmeBundle:Region',
'property_path'=>false,
'empty_value'=>'Choose a value',
'required'=>true,
'label'=>'Region'
)));
Lưu ý rằng bạn cần phải thêm nhà máy $ đến 'sử dụng' về việc xử lý sự kiện đóng cửa:
$builder->addEventListener(FormEvents::POST_SET_DATA, function (DataEvent $event) use ($refreshTopic, $factory) {
Dưới đây là toàn bộ lớp mẫu:
<?php
namespace AAA\CoreBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Form;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;
use AAA\CoreBundle\Entity\ClassYear;
use AAA\CoreBundle\Entity\Field;
use AAA\CoreBundle\Entity\Lesson;
use AAA\CoreBundle\Form\LessonContentForm;
class LessonDetailForm extends AbstractType
{
public $country;
function __construct($country=null) {
// Get country for classyear dropdown list
$this->country = $country;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$factory = $builder->getFormFactory();
$builder->add('name', null, array('label'=>'Titre de la leçon'));
$builder->add('description', 'textarea', array('label'=>'Description (définition conceptuelle) Qu\'est-ce que c\'est ? Et à quoi ça sert ? (importance, utilité)'));
$builder->add('text', 'textarea', array('label'=>'Leçon', 'required'=>false)); // Can't set 'required' on textareas used by TinyMCE
$builder->add('reperes', 'textarea', array('label'=>'Repères (détectionel) - Quels sont les éléments qui me permettent de repérer que je dois penser à ce concept ?', 'required'=>false));
$builder->add('other_topic', null, array(
'required' => false,
'mapped' => false
));
$refreshField = function ($form, $classyear) use ($factory) {
/** @var FormFactory $factory */
/** @var Form $form */
$form->add($factory->createNamed('field','entity',null, array(
'class' => 'AAA\CoreBundle\Entity\Field',
'mapped' => false,
'label' => 'Matière',
'empty_value' => 'Sélectionne une valeur',
'empty_data' => null,
'required' => false,
'query_builder' => function (EntityRepository $repository) use ($classyear) {
$qb = $repository->createQueryBuilder('field')
->innerJoin('field.classyear', 'classyear');
if($classyear instanceof ClassYear) {
$qb = $qb->where('field.classyear = :classyear')
->setParameter('classyear', $classyear);
} elseif(is_numeric($classyear)) {
$qb = $qb->where('classyear.id = :classyear_id')
->setParameter('classyear_id', $classyear);
} else {
$qb = $qb->where('0 = 1');
}
return $qb;
}
)));
};
$refreshTopic = function ($form, $field) use ($factory) {
/** @var FormFactory $factory */
/** @var Form $form */
$form->add($factory->createNamed('topic','entity',null, array(
'class' => 'AAA\CoreBundle\Entity\Topic',
'property' => 'name',
'label' => 'Sujet',
'empty_value' => 'Sélectionne une valeur',
'empty_data' => null,
'required' => false,
'query_builder' => function (EntityRepository $repository) use ($field) {
$qb = $repository->createQueryBuilder('topic')
->innerJoin('topic.field', 'field');
if($field instanceof Field) {
$qb = $qb->where('topic.field = :field')
->setParameter('field', $field);
} elseif(is_numeric($field)) {
$qb = $qb->where('field.id = :field_id')
->setParameter('field_id', $field);
} else {
$qb = $qb->where('0 = 1');
}
return $qb;
}
)));
};
// Populate ddl to show form
$country = $this->country;
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($refreshTopic, $refreshField, $factory, $country) {
/** @var Lesson $data */
$data = $event->getData();
$form = $event->getForm();
// Test if null because this event is called 2 times, only the second time with the actual Lesson object (which has null values in the creation case)
if($data != null)
// In case of creation
if($data->getId()==null) {
// Creates empty fields
$refreshTopic($form, null);
$refreshField($form, null);
}
// In case of edition
else {
if ($data->getTopic() != null) {
$refreshTopic($form, $data->getTopic()->getField());
if ($data->getTopic()->getField() != null) {
$refreshField($form, $data->getTopic()->getField()->getClassYear());
}
}
else {
$refreshField($form, null);
$refreshTopic($form, null);
}
}
/** @var FormFactory $factory */
$form->add($factory->createNamed('classyear', 'entity', null, array(
'class' => 'AAACoreBundle:ClassYear',
'property' => 'name'.$country,
'mapped' => false,
'label' => 'Année',
'empty_value' => 'Sélectionne une valeur',
'empty_data' => null,
'required' => false,
'query_builder' => function (EntityRepository $repository) {
return $repository->createQueryBuilder('classyear')
->orderBy('classyear.sort');
}
)));
});
// Populate ddl when form was posted
$builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) use ($refreshTopic, $refreshField) {
$form = $event->getForm();
$data = $event->getData();
if(array_key_exists('classyear', $data)) {
$refreshField($form, $data['classyear']);
}
if(array_key_exists('field', $data)) {
$refreshTopic($form, $data['field']);
}
});
// Select value in ddl when editing
$builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) use ($refreshTopic) {
/** @var Lesson $data */
$data = $event->getData();
$form = $event->getForm();
if (null === $data || null === $data->getId()) {
return;
}
if ($data->getTopic() != null) {
$form->get('field')->setData($data->getTopic()->getField());
if ($data->getTopic()->getField() != null) {
$form->get('classyear')->setData($data->getTopic()->getField()->getClassYear());
}
}
});
}
public function getName()
{
return 'LessonDetailForm';
}
/** @param OptionsResolverInterface $resolver */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AAA\CoreBundle\Entity\Lesson'
));
}
}
?>
tôi có một câu hỏi cho bạn Thomas, tôi có một sự phụ thuộc thả xuống tương tự như trong hệ thống của tôi. Trường hợp của tôi là tôi tạo biểu mẫu và tôi ràng buộc nó với các giá trị khác (yêu cầu thực sự), làm cách nào tôi có thể đặt dữ liệu 'vùng' và tiếp tục làm việc cả khi tôi tạo biểu mẫu và tôi không ràng buộc nó và khi tôi ràng buộc dữ liệu với yêu cầu? – eagleoneraptor
Xin lỗi, tôi thực sự không hiểu câu hỏi đó. :) (nhớ rằng ràng buộc của các hình thức đã được cải thiện trong 2.1, vì vậy bạn chỉ cần gọi bind() và không bindRequest() nữa – Thomas
Xin chào thomas.Tôi đang đấu tranh như địa ngục để làm những gì bạn đã làm. các sự kiện không còn nữa. Liên kết đã chết Bạn có thể là con trai và chỉnh sửa câu trả lời của bạn để những người khác như tôi có thể tiến lên phía trước. Điều đó thực sự tuyệt vời :) Cảm ơn bạn trước. Chúc mừng. Marc – Marc