web-dev-qa-db-fra.com

Symfony2 changer les options de champ d'un formulaire incorporé

Ma question est essentiellement la suivante: est-il possible de changer l’option d’un champ d’un formulaire incorporé pour à partir du formulaire parent? 

Pour illustrer le problème, considérez ceci; J'ai une classe de type de formulaire parent comme ceci:

class FruitFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', 'text')
            ->add('Apple', new AppleFormType())
        ;
    }

et une classe de type de formulaire enfant qui est dans un bundle séparé et que je préférerais ne pas modifier, comme ceci: 

class AppleFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', 'text')
            ->add('qty', 'integer', array('label' => 'rubbish label')
        ;
    }

et je veux changer le libellé de qty en quelque chose d'autre, mais je veux le faire uniquement dans le FruitForm, pas partout où le AppleForm est utilisé. J'avais espéré pouvoir faire quelque chose comme:

class FruitFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', 'text')
            ->add('Apple', new AppleFormType(), array('qty' => array('label' => 'better label')))
        ;
    }

ou:

class FruitFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', 'text')
            ->add('Apple', new AppleFormType())
        ;

        $builder->get('Apple')->get('qty')->setOption('label', 'better label');
    }

mais ni l'un ni l'autre (et plusieurs autres tentatives) ne m'ont tous échoué. Il n’existe pas de méthode setOption que je puisse voir. 

Est-ce que quelqu'un connaît un moyen de faire cela?

Merci

19
lopsided

Je souhaitais également modifier les options, le cas évident "changer l'étiquette" pour un champ existant du FOSUserBundle. Je sais que je pourrais le faire avec Twig ou avec des traductions.

@redbirdo m'a indiqué la bonne direction avec "il apparaît que l'ajout d'un champ du même nom le remplacera". Voici la solution:

$field = $builder->get('username');         // get the field
$options = $field->getOptions();            // get the options
$type = $field->getType()->getName();       // get the name of the type
$options['label'] = "Login Name";           // change the label
$builder->add('username', $type, $options); // replace the field
40
Peter Wooster

Merci beaucoup à Peter Wooster. Dans Symfony 3.0, je devais utiliser quelque chose d'un peu différent:

J'ai un type de formulaire personnalisé en ajoutant des champs comme suit:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('my_field', ChoiceType::class, [
        // Some options here...
        'multiple' => false,
    ]);
}

Et dans un autre type de formulaire personnalisé, je dois étendre le type ci-dessus et modifier certaines options:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    parent::buildForm($builder, $options);

    $myField = $builder->get('my_field');
    $fieldOptions = $myField->getOptions();
    // Retrieve the FormType. That is the part that is different.
    $fieldType = get_class($myField->getType()->getInnerType());
    $fieldOptions['multiple'] = true;
    // I can obviously put the name 'my_field' directly here
    $builder->add($myField->getName(), $fieldType, $fieldOptions);
}

Merci aux réponses ci-dessus, j'espère que le mien aide!

8
peamak

Essayez quelque chose comme ça:

class AppleFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', 'text')
            ->add('qty', 'integer', array('label' => $options['qtyLabel'])
        ;
    }

    public function getDefaultOptions()
    {
        return array(
            'qtyLabel' = 'rubbish label';
        );
    }
}

et:

class FruitFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', 'text')
            ->add('Apple', new AppleFormType(), array('qtyLabel' => 'better label'))
        ;
    }
}
8
redbirdo

Je suis dans le cas où je ne peux pas accéder au code du générateur de formulaire mais que je dois remplacer une option de champ pour ajouter un 'required' => true.

En développant @ peter-wooster et @thedamnedrhino pour répondre à un problème de symfony sur github ( https://github.com/symfony/symfony/issues/11188 ), je termine avec ce morceau de code.

$field = $form->get('combinaisons');
$options = $field->getConfig()->getOptions();
$type = $field->getConfig()->getType()->getName();
$options['required'] = true;
unset($options['em']);
$form->add('combinaisons', $type, $options); 

Cela fonctionne très bien avec symfony/symfony: 2.3.21, doctrine/doctrine-bundle: 1.2.0 et doctrine/orm: 2.3.6

3
Daishi

Modifier la vue est souvent beaucoup plus facile pour ce type de changement.

$view->vars['label'] = 'New label';

En règle générale, votre vue sera un formulaire parent. Elle pourrait donc ressembler à ceci: changez 'Date'> 'Date de publication':

$view = $form->createView(...);
$view->children['date']->vars['label'] = 'Publication date';

Si votre formulaire est encapsulé dans son propre type, vous pouvez utiliser la fonction finishView:

public function finishView(FormView $view, FormInterface $form, array $options)
{
    $view->children['date']->vars['label'] = 'Publication date';
}

Étant donné que la plupart de ce qui est finalement transmis au moteur de modélisation pour le rendu est sous forme de tableau simple, vous pouvez jouer avec beaucoup de choses à ce stade.

0
Henry