Я столкнулся с проблемой, следуя поваренной книге Symfony для коллекций форм с добавлением / удалением. См .: http://symfony.com/doc/current/cookbook/form/form_collections.html.
Теперь, по какой-то причине, если я динамически добавляю строку формы, но не заполняю ни одно из ее полей , я получаю следующую ошибку:
ContextErrorException: Catchable Fatal Error: Argument 1 passed to Project::addTask() must be an instance of Task, null given in D:\web_workspace\wedding\src\testapp.php line 82
Я хотел бы, чтобы люди могли иметь пустые строки в форме, которые просто проигнорируются. Например, если вы нажмете «Добавить задачу» несколько раз, но не заполняете последнюю строку, форма должна быть отправлена, и последняя строка должна быть проигнорирована.
Я создал очень простую демонстрацию Silex, которая вписывается всего в пару файлов. Я остановлюсь на этом здесь, но полный пример здесь, и его можно запустить, просто добавив Silex через композитор: https://gist.github.com/mattsnowboard/7065865
У меня есть следующие модели (только Project
котором есть описание и коллекция Task
s)
class Task { protected $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; return $this; } } class Project { protected $description; protected $tasks; public function __construct() { $this->tasks = array(); } public function getDescription() { return $this->description; } public function setDescription($description) { $this->description = $description; return $this; } public function getTasks() { return $this->tasks; } public function addTask(Task $task) { if (!is_null($task) && !in_array($task, $this->tasks)) { $this->tasks[] = $task; } return $this; } public function removeTask(Task $task) { if (!is_null($task)) { $this->tasks = array_diff($this->tasks, array($task)); } return $this; } }
Мои формы следующие
class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('name', 'text', array( 'required' => false )); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => '\Task', )); } public function getName() { return 'task'; } } class ProjectType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('description', 'text', array()) ->add('tasks', 'collection', array( 'type' => new TaskType(), 'allow_add' => true, 'by_reference' => false, 'allow_delete' => true, 'required' => false )) ->add('submit', 'submit') ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => '\Project', )); } public function getName() { return 'project'; } }
Контроллер добавляет некоторые тестовые данные в форму и просто печатает данные при их отправке:
$app->match('/', function (Request $request) use ($app) { $project = new Project(); // dummy code $task1 = new Task(); $task1->setName('A Task'); $project->addTask($task1); // end dummy code $form = $app['form.factory']->create(new ProjectType(), $project); $form->handleRequest($request); if ($form->isValid()) { $data = $form->getData(); $debug = print_r($data, true); echo $debug; } return $app['twig']->render('test.html.twig', array( 'form' => $form->createView(), )); }) ->method('GET|POST');
В основном это мнение, и образец javascript из поваренной книги
{{ form_start(form) }} {{ form_row(form.description) }} <h3>Tags</h3> <ul class="tasks" data-prototype="{{ form_widget(form.tasks.vars.prototype)|e }}"> {# iterate over each existing tag and render its only field: name #} {% for task in form.tasks %} <li>{{ form_row(task.name) }}</li> {% endfor %} </ul> {{ form_widget(form.submit) }} {{ form_end(form) }}
Я что-то пропустил? Это ошибка? Я чувствую, что этот пример, который очень близок к поваренной книге, должен работать довольно легко …
Обновлено : Удаление "allow_deleted"
самом деле не исправляет это.
Извините, я понял, тип collection
не должен иметь 'required' => false
$builder->add('description', 'text', array()) ->add('tasks', 'collection', array( 'type' => new TaskType(), 'allow_add' => true, 'by_reference' => false, 'allow_delete' => true, 'required' => false ))
Должно быть
$builder->add('description', 'text', array()) ->add('tasks', 'collection', array( 'type' => new TaskType(), 'allow_add' => true, 'by_reference' => false, 'allow_delete' => true ))