Как я могу передать конкретную переменную итерации в Конструктор форм в коллекции форм в Symfony 3?


У меня есть оценка, в которой есть разные вопросы (пункты), и каждый пункт имеет определенное количество возможных вариантов.

Мне нужно передать количество вариантов и метки каждого вопроса, чтобы создать форму для каждого элемента (вопроса).

Я могу передавать переменные из "родительской" формы в коллекцию форм, но я не могу понять, как передать переменную, специфичную для каждой итерации, в свойстве оценки "ответы".

В моем контроллер:

$evaluation = new Evaluation();
$answers = array();
// i set each answer to default 0, for the form to place them in view
foreach ($items as $index => $item) {
    $answers[$index] = array('value' => 0, 'item_id' => $item->getId());
}
$evaluation->setAnswers($answers);

$formBuilder = $this->createFormBuilder($evaluation);

$formBuilder->add("answers", CollectionType::class, array(
    'entry_type' => AnswerType::class,
    //here i pass all the items objects array to the AnswerType form.
    'entry_options' => array(
        'items' => $items,
    ),
    'allow_delete' => false,
    'allow_add' => false,
));

И чем в классе формы типа ответа:

class AnswerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $choices = array();

        // here I have all the items available in $options['items'];
        // but each item has a specific number of choices, and I need the current one that is being built
        // and I also need other info form the item like the question it self

        for($i = 1; $i <= $current_item_number_of_choices_that_i_dont_have;$i++){
            $choices[$i] = $i;
        }

        $builder->add('value', ChoiceType::class, array(
            'choices_as_values' => true,
            'multiple'=>false,
            'expanded'=>true,
            'choices' => $choices,
            'label' => $current_item_text_label_that_I_also_need
        ));

    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'items' => null
        ));
    }
}

Спасибо!:)

Author: yceruto, 2017-05-06

1 answers

Вероятно, CollectionType не тот тип, который вам сейчас нужен для его достижения, потому что он скрывает слой, который вам нужно обработать (текущий элемент). Поэтому лучше всего было бы добавить коллекцию ответов самостоятельно. Что-то вроде этого:

class AnswerCollectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        foreach ($options['items'] as $index => $item) {
            $builder->add($index + 1, AnswerType::class, [
                'item' => $item,
            ]);
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setRequired('items');
    }
}

class AnswerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $item = $options['item'];

        $choices = [];
        for ($i = 1; $i <= $item->getNumChoices(); $i++) {
            $choices[$i] = $i;
        }

        $builder->add('value', ChoiceType::class, [
            'label' => $item->getLabel(),
            'choices' => $choices,
            'expanded' => true,
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setRequired('item');
    }
}

Обратите внимание, что AnswerType теперь требуется опция item, необходимая для правильного построения текущей формы выбора.

$formBuilder->add('answers', AnswerCollectionType::class, [
    'items' => $items,
])

С другой стороны, обходной путь CollectionType является более сложным (с использованием событий), для которого требуется статический внутренний счетчик, чтобы знать текущий элемент.

См. http://symfony.com/doc/current/form/dynamic_form_modification.html подробнее.

 2
Author: yceruto, 2017-05-08 19:05:43