web-dev-qa-db-fra.com

Comment définir la valeur par défaut pour le champ de formulaire dans Symfony2?

Existe-t-il un moyen simple de définir une valeur par défaut pour un champ de formulaire texte?

133
Ondrej Slinták

Peut être utilisé lors de la création facilement avec:

->add('myfield', 'text', array(
     'label' => 'Field',
     'empty_data' => 'Default value'
))
99
webda2l

vous pouvez définir la valeur par défaut avec empty_data

$builder->add('myField', 'number', ['empty_data' => 'Default value'])
114
rkmax

J'ai envisagé cela plusieurs fois dans le passé, alors j'ai pensé noter les différentes idées que j'ai eues/utilisées. Quelque chose peut être utile, mais aucune n’est une solution Symfony2 "parfaite".

Constructeur Dans l'entité, vous pouvez faire $ this-> setBar ('valeur par défaut'); mais cela s'appelle chaque fois que vous chargez l'entité (db ou pas) et c'est un peu brouillon. Cela fonctionne cependant pour chaque type de champ car vous pouvez créer des dates ou tout ce dont vous avez besoin.

Si les déclarations dans get's Je ne le ferais pas, mais vous pourriez le faire.

return ( ! $this->hasFoo() ) ? 'default' : $this->foo;

sine/instance. Appelez une classe statique de fonction/secondaire qui vous fournit une entité par défaut pré-renseignée avec des données. Par exemple.

function getFactory() {
    $obj = new static();
    $obj->setBar('foo');
    $obj->setFoo('bar');

   return $obj;
}

Ce n'est pas vraiment idéal étant donné que vous devrez conserver cette fonction si vous ajoutez des champs supplémentaires, mais cela signifie que vous séparez les paramètres de données/défaut et ceux générés à partir de la base de données. De même, vous pouvez avoir plusieurs getFactories si vous voulez différentes données par défaut.

Entités étendues/Reflection Créez une entité extensible (par exemple, FooCreate étend Foo) qui vous donnera les données par défaut au moment de la création (via le constructeur). Semblable à l’idée Usine/instance, mais une approche différente - je préfère les méthodes statiques personnellement.

Définir les données avant le formulaire de construction Dans les constructeurs/services, vous savez si vous avez une nouvelle entité ou si elle a été renseignée à partir de la base de données. Il est donc plausible d'appeler des données d'ensemble sur les différents champs lorsque vous saisissez une nouvelle entité. Par exemple.

if( ! $entity->isFromDB() ) {
     $entity->setBar('default');
     $entity->setDate( date('Y-m-d');
     ...
}
$form = $this->createForm(...)

Événements de formulaire Lorsque vous créez le formulaire, vous définissez des données par défaut lors de la création des champs. Vous substituez cet écouteur d'événements PreSetData à l'utilisation. Le problème, c’est que vous dupliquez la charge de travail du formulaire/le code en double et le rend plus difficile à gérer/à comprendre.

Formulaires étendus Similaire aux événements de formulaire, mais vous appelez le type différent selon qu'il s'agit d'une base de données ou d'une nouvelle entité. J'entends par là que vous avez FooType qui définit votre formulaire de modification, BarType étend FooType et définit toutes les données dans les champs. Dans votre contrôleur, vous choisissez ensuite simplement le type de formulaire à activer. Cela craint si vous avez un thème personnalisé et que, tout comme les événements, crée trop de maintenance à mon goût.

Twig Vous pouvez créer votre propre thème et définir les données par défaut à l'aide de l'option value également lorsque vous le faites champ par champ. Si vous souhaitez que vos modèles soient propres et que le formulaire soit réutilisable, rien ne vous empêche de l'intégrer dans un thème de formulaire. par exemple.

form_widget(form.foo, {attr: { value : default } });

JS Il serait trivial de renseigner le formulaire avec une fonction JS si les champs sont vides. Vous pouvez faire quelque chose avec des espaces réservés, par exemple. C'est une mauvaise, mauvaise idée cependant.

Forms as a service Pour l'un de mes grands projets, j'ai créé un service qui générait tous les formulaires, effectuait tout le traitement, etc. En effet, les formulaires devaient être utilisés sur plusieurs contrôleurs. dans plusieurs environnements et alors que les formulaires étaient générés/traités de la même manière, ils étaient affichés/avec lesquels ils interagissaient différemment (par exemple, traitement des erreurs, redirections, etc.). L'intérêt de cette approche réside dans le fait que vous pouvez utiliser des données par défaut, faire tout ce dont vous avez besoin, gérer les erreurs de manière générique, etc., et tout est encapsulé au même endroit.

Conclusion D'après ce que je vois, vous rencontrez encore et encore le même problème: où trouver les données par défaut?

  • Si vous le stockez au niveau de la base de données/doctrine, que se passe-t-il si vous ne souhaitez pas stocker les valeurs par défaut à chaque fois?
  • Si vous la stockez au niveau de l'entité, que se passera-t-il si vous souhaitez réutiliser cette entité ailleurs sans aucune donnée?
  • Si vous le stockez au niveau de l'entité et ajoutez un nouveau champ, voulez-vous que les versions précédentes aient cette valeur par défaut lors de la modification? Il en va de même pour la valeur par défaut dans la base de données ...
  • Si vous le stockez au niveau du formulaire, cela est-il évident lorsque vous souhaitez conserver le code ultérieurement?
  • Si c'est dans le constructeur que se passe-t-il si vous utilisez le formulaire à plusieurs endroits?
  • Si vous le poussez au niveau JS, alors vous êtes allé trop loin - les données ne devraient pas être dans la vue, peu importe JS (et nous ignorons la compatibilité, les erreurs de rendu, etc.)
  • Le service est excellent si, comme moi, vous l'utilisez à plusieurs endroits, mais il est excessif de créer un simple formulaire d'ajout/modification sur un site ...

À cette fin, j'ai abordé le problème différemment à chaque fois. Par exemple, une option "newsletter" de formulaire d'inscription est facilement (et logiquement) définie dans le constructeur juste avant de créer le formulaire. Lorsque je construisais des collections de formulaires qui étaient liés les uns aux autres (par exemple, des boutons radio de types de formulaires différents reliés entre eux), j'ai utilisé Event Listeners. Lorsque j'ai construit une entité plus complexe (par exemple une entité nécessitant des enfants ou un grand nombre de données par défaut), j'ai utilisé une fonction (par exemple, 'getFactory') pour le créer comme j'en avais besoin.

Je ne pense pas qu'il existe une approche "correcte", car chaque fois que j'ai eu cette exigence, cela a été légèrement différent.

Bonne chance! J'espère que je vous ai donné matière à réflexion de toute façon et que je n'ai pas trop flâné;)

62
stefancarlton

Si vous devez définir une valeur par défaut et que votre formulaire se rapporte à l'entité, vous devez utiliser l'approche suivante:

// buildForm() method
public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder
    ...
    ->add(
        'myField',
        'text',
        array(
            'data' => isset($options['data']) ? $options['data']->getMyField() : 'my default value'
        )
    );
}

Sinon, myField sera toujours défini sur la valeur par défaut, au lieu d’obtenir la valeur de l’entité.

42
Dmitriy

Vous pouvez définir la valeur par défaut du champ associé dans votre classe de modèle (dans la définition de mappage ou définir la valeur vous-même).

De plus, FormBuilder vous permet de définir les valeurs initiales avec la méthode setData () . Le générateur de formulaire est passé à la méthode createForm () de votre classe de formulaire.

Vérifiez également ce lien: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class

19
Jakub Zalas

Si votre formulaire est lié à une entité, définissez simplement la valeur par défaut sur l'entité elle-même à l'aide de la méthode de construction:

public function __construct()
{
    $this->field = 'default value';
}
16
Hubert Perron

Approche 1 (de http://www.cranespud.com/blog/dead-simple-default-values-on-symfony2-forms/ )

Définissez simplement la valeur par défaut dans votre entité, soit dans la déclaration de variable, soit dans le constructeur:

class Entity {
    private $color = '#0000FF';
    ...
}

ou

class Entity {
    private $color;

    public function __construct(){
         $this->color = '#0000FF';
         ...
    }
    ...
}

Approche 2 d'un commentaire dans le lien ci-dessus, ainsi que la réponse de Dmitriy (pas celle acceptée) de Comment définir la valeur par défaut du champ de formulaire dans Symfony2?

Ajoutez la valeur par défaut à l'attribut data lors de l'ajout du champ avec FormBuilder, adapté de la réponse de Dmitriy.

Notez que cela suppose que la propriété aura et n'aura que la valeur null s'il s'agit d'une nouvelle entité et non d'une entité existante.

public function buildForm(FormBuilderInterface $builder, array $options) {
    $builder->add('color', 'text', array(
            'label' => 'Color:',
            'data' => (isset($options['data']) && $options['data']->getColor() !== null) ? $options['data']->getColor() : '#0000FF'
        )
    );
}
12
crysallus

Vous pouvez définir une valeur par défaut, par exemple pour la forme message, comme ceci:

$defaultData = array('message' => 'Type your message here');
$form = $this->createFormBuilder($defaultData)
    ->add('name', 'text')
    ->add('email', 'email')
    ->add('message', 'textarea')
    ->add('send', 'submit')
    ->getForm();

Si votre formulaire est mappé à une entité, vous pouvez procéder comme suit (par exemple, nom d'utilisateur par défaut):

$user = new User();
$user->setUsername('John Doe');

$form = $this->createFormBuilder($user)
    ->add('username')
    ->getForm();
9

Une solution générale pour tout cas/approche, principalement en utilisant un formulaire sans classe ou lorsque nous avons besoin d'un accès à des services pour définir la valeur par défaut:

// src/Form/Extension/DefaultFormTypeExtension.php

class DefaultFormTypeExtension extends AbstractTypeExtension
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if (null !== $options['default']) {
            $builder->addEventListener(
                FormEvents::PRE_SET_DATA,
                function (FormEvent $event) use ($options) {
                    if (null === $event->getData()) {
                        $event->setData($options['default']);
                    }
                }
            );
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefault('default', null);
    }

    public function getExtendedType()
    {
        return FormType::class;
    }
}

et enregistrez l'extension de formulaire:

app.form_type_extension:
    class: App\Form\Extension\DefaultFormTypeExtension
    tags:
        - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FormType }

Après cela, nous pouvons utiliser l’option default dans n’importe quel champ de formulaire:

$formBuilder->add('user', null, array('default' => $this->getUser()));
$formBuilder->add('foo', null, array('default' => 'bar'));
9
yceruto

Ne pas utiliser:

'data' => 'Default value'

Lire ici: https://symfony.com/doc/current/reference/forms/types/form.html#data

"L'option data remplace toujours la valeur prise dans les données du domaine (objet) lors du rendu. Cela signifie que la valeur de l'objet est également remplacée lorsque le formulaire modifie un objet déjà persistant, ce qui entraîne sa perte. valeur persistante lors de l'envoi du formulaire. "


Utilisez le suivant:

Disons que, pour cet exemple, vous avez un Entity Foo et qu'il existe un champ "actif" (dans cet exemple, il s'agit de CheckBoxType, mais le processus est identique pour tous les autres types), que vous souhaitez vérifier par défaut.

Dans votre classe FooFormType, ajoutez:

...
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
...
public function buildForm( FormBuilderInterface $builder, array $options )
{
    ...

    $builder->add('active', CheckboxType::class, array(
        'label' => 'Active',
    ));

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function(FormEvent $event){                 
            $foo = $event->getData();
            // Set Active to true (checked) if form is "create new" ($foo->active = null)
            if(is_null($foo->getActive())) $foo->setActive(true);
        }
   );
}
public function configureOptions( OptionsResolver $resolver )
{
    $resolver->setDefaults(array(
        'data_class' => 'AppBundle:Foo',
    ));
}
6
cure85
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
     $form = $event->getForm(); 
     $data = $event->getData(); 

     if ($data == null) {
         $form->add('position', IntegerType::class, array('data' => 0));
     }

});
6
ziiweb

Si vous utilisez un FormBuilder dans symfony 2.7 pour générer le formulaire, vous pouvez également transmettre les données initiales à la méthode createFormBuilder du contrôleur.

$values = array(
    'name' => "Bob"
);

$formBuilder = $this->createFormBuilder($values);
$formBuilder->add('name', 'text');
4
Bob

Ma solution:

$defaultvalue = $options['data']->getMyField();
$builder->add('myField', 'number', array(
            'data' => !empty($defaultvalue) ? $options['data']->getMyField() : 0
        )) ;
4
trocolo

Juste pour que je comprenne le problème.

Vous souhaitez ajuster la manière dont le formulaire est construit en fonction des données de votre entité. Si l'entité est en cours de création, utilisez une valeur par défaut. Si l'entité est existante, utilisez la valeur de la base de données.

Personnellement, je pense que la solution de @ MolecularMans est la voie à suivre. En fait, je définirais les valeurs par défaut dans le constructeur ou dans la déclaration de propriété. Mais vous ne semblez pas aimer cette approche.

Au lieu de cela, vous pouvez suivre ceci: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

Vous bloquez un écouteur sur votre type de formulaire et vous pouvez ensuite examiner votre entité et ajuster les instructions constructeur-> add en conséquence, en fonction de la création d'une entité nouvelle ou existante. Vous devez toujours spécifier vos valeurs par défaut quelque part, mais vous pouvez simplement les coder dans votre écouteur. Ou passez-les dans le type de formulaire.

On dirait que beaucoup de travail cependant. Mieux vaut simplement passer l'entité au formulaire avec ses valeurs par défaut déjà définies.

4
Cerad

Souvent, pour les valeurs par défaut init de la forme, j'utilise des fixtures. Bien que ce chemin ne soit pas facile, mais très confortable.

Exemple:

class LoadSurgeonPlanData implements FixtureInterface
{
    public function load(ObjectManager $manager)
    {
        $surgeonPlan = new SurgeonPlan();

        $surgeonPlan->setName('Free trial');
        $surgeonPlan->setPrice(0);
        $surgeonPlan->setDelayWorkHours(0);
        $surgeonPlan->setSlug('free');

        $manager->persist($surgeonPlan);
        $manager->flush();        
    }   
}

Pourtant, les champs de type symfony ont l'option data .

Exemple

$builder->add('token', 'hidden', array(
    'data' => 'abcdef',
));
3
Mikhail Schedrakov

Il existe un moyen très simple, vous pouvez définir les paramètres par défaut comme ici:

$defaults = array('sortby' => $sortby,'category' => $category,'page' => 1);

$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
3
Alsatian

Si vous définissez 'data' dans votre formulaire de création, cette valeur ne sera pas modifiée lors de la modification de votre entité.

Ma solution est:

public function buildForm(FormBuilderInterface $builder, array $options) {
    // In my example, data is an associated array
    $data = $builder->getData();

    $builder->add('myfield', 'text', array(
     'label' => 'Field',
     'data' => array_key_exits('myfield', $data) ? $data['myfield'] : 'Default value',
    ));
}

Au revoir.

2
Quentin Machard

Les valeurs par défaut sont définies en configurant l'entité correspondante. Avant de lier l'entité à la forme, définissez son champ de couleur sur "# 0000FF":

// controller action
$project = new Project();
$project->setColor('#0000FF');
$form = $this->createForm(new ProjectType(), $project);
1
Molecular Man

Je règle généralement la valeur par défaut pour un champ spécifique de mon entité:

/**
 * @var int
 * @ORM\Column(type="integer", nullable=true)
 */
protected $development_time = 0;

Cela fonctionnera pour les nouveaux enregistrements ou s'il ne s'agit que de mettre à jour ceux existants.

1
matotej

Si ce champ est lié à une entité (est une propriété de cette entité), vous pouvez simplement lui attribuer une valeur par défaut.

Un exemple:

public function getMyField() {
    if (is_null($this->MyField)) {
        $this->setMyField('my default value');
    }
    return $this->MyField;
}
1
Andrei Sandulescu

Comme Brian a demandé:

empty_data semble ne définir le champ à 1 que s'il est soumis sans valeur. Qu'en est-il lorsque vous voulez que le formulaire affiche par défaut 1 dans l'entrée en l'absence de valeur?

vous pouvez définir la valeur par défaut avec empty_value

$builder->add('myField', 'number', ['empty_value' => 'Default value'])
1
Snowirbis

J'ai résolu ce problème en ajoutant valeur dans attr:

->add('projectDeliveringInDays', null, [
    'attr' => [
          'min'=>'1',
          'value'=>'1'
          ]
     ])
0
Kaxa

Je résous ce problème comme ceci dans symfony 3.4

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('field');

    $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $e) {
        if (!$e->getData()) {
            // in create new mode
            $e->getForm()
                ->add('field', NumberType::class, ['data' => 0 /*Default value here*/] );
        }
    });
}
0
user9133301