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


137

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


1
oui, mais les réponses données dans cette question ne sont pas satisfaisantes / ne fonctionnent pas ... J'ajouterai un "Edit" pour expliquer pourquoi :-)
herrjeh42

Il semble que la solution «parfaite» que vous recherchez soit pour un champ d'avoir une option «default_value». La chose est, actuellement non , donc je ne pense pas que la solution parfaite que vous recherchez existe actuellement. La seule chose que fournit symfony (voir le lien) est l'option data. Donc, le si-alors est la seule approche que je peux voir atm. Même s'il y avait une option 'default_value' sur le champ lui-même, j'imagine que cela ferait essentiellement la même chose en interne de toute façon.
crysallus

De plus, j'ai apporté une correction à ma réponse dans l'approche 2 selon mes commentaires ci-dessous. Si cela résout le problème de syntaxe que vous avez mentionné au point 2, vous voudrez peut-être modifier ce commentaire. Ou faites-moi savoir quel est le problème, et je corrigerai ma réponse.
crysallus

1
@Crone cette question a été posée 2 ans plus tôt
Ondrej Slinták

1
@ OndrejSlinták Je n'ai pas voté pour fermer non plus en tant que dupe, mais pour info: peu importe laquelle est venue en premier, " Si la nouvelle question est une meilleure question ou a de meilleures réponses, alors votez pour fermer l'ancienne comme un doublon du nouveau. "
Jeff Puckett

Réponses:


105

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

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

11
Pour Symfony 2.1, j'avais besoin de changer la 'data'clé en'value'
Edd

175
Cela ne définit pas seulement une valeur par défaut, cela forcera également toujours la valeur dans n'importe quel contexte. Pas ce que j'appellerais une "valeur par défaut" ...
Hubert Perron

4
J'ai décliné cette solution car ce n'est pas une solution au problème (comme Hubert Perron l'a mentionné ci-dessus). J'essaie d'obtenir une meilleure solution dans ce post stackoverflow.com/questions/17986481/…
herrjeh42

13
Il s'agit de la valeur initiale, la valeur par défaut estempty_data
Pierre de LESPINAY

3
dataest inutile - il écrase la valeur enregistrée. empty_datan'affiche pas la valeur, il l'utilise lors de la soumission d'une valeur vide et rend impossible l'enregistrement des choix non cochés.
moldcraft

115

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

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

29
Les données de réglage ne définissent pas la valeur par défaut. Cette réponse est la bonne.
Alexei Tenitski

9
Cela semble ne définir le champ sur 1 que lorsqu'il est soumis sans valeur. Qu'en est-il lorsque vous souhaitez que le formulaire affiche par défaut 1 dans l'entrée lorsqu'aucune valeur n'est présente?
Brian

Dans mes tests, empty_data ne me permet pas de remplacer la valeur par défaut d'un champ soumis vide, par exemple si vous voulez enregistrer dans la base de données en tant que 0 au lieu de NULL. Ce bug est toujours en suspens pour autant que je sache
Chadwick Meyer

63

J'ai envisagé cela à quelques reprises dans le passé, alors j'ai pensé noter les différentes idées que j'avais / utilisées. Quelque chose pourrait ê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 est appelé chaque fois que vous chargez l'entité (db ou non) et est un peu compliqué. 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, je ne le ferais pas, mais vous pourriez.

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

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

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

   return $obj;
}

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

Entités étendues / de réflexion Créez une entité étendue (par exemple, FooCreate étend Foo) qui vous donne les données par défaut au moment de la création (via le constructeur). Similaire à l'idée Factory / instance, une approche différente - je préfère personnellement les méthodes statiques.

Définir les données avant le formulaire de génération Dans les constructeurs / service, vous savez si vous avez une nouvelle entité ou si elle a été remplie à 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 les données par défaut lors de la création des champs. Vous remplacez cet écouteur d'événement Use PreSetData. Le problème avec cela est que vous dupliquez la charge de travail du formulaire / dupliquez le code et que vous le rendez plus difficile à maintenir / comprendre.

Formulaires étendus Semblable aux événements Form, mais vous appelez le type différent selon qu'il s'agit d'une entité db / new. Je veux dire par là que vous avez FooType qui définit votre formulaire d'édition, BarType étend FooType et définit toutes les données dans les champs. Dans votre contrôleur, vous choisissez alors simplement le type de formulaire à lancer. Cela craint si vous avez un thème personnalisé et que vous aimez les événements, cela crée trop de maintenance à mon goût.

Twig Vous pouvez créer votre propre thème et les données par défaut en utilisant également l'option de valeur lorsque vous le faites sur une base par champ. Rien ne vous empêche de l'envelopper dans un thème de formulaire si vous souhaitez garder vos modèles propres et le formulaire réutilisable. par exemple

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

JS Ce serait trivial de remplir 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, une mauvaise idée cependant.

Formulaires en tant que service Pour l'un des grands projets basés sur les formulaires que j'ai réalisés, j'ai créé un service qui générait tous les formulaires, effectuait tout le traitement, etc. C'était parce que les formulaires devaient être utilisés sur plusieurs contrôleurs dans plusieurs environnements et pendant que les formulaires ont été générés / traités de la même manière, ils ont été affichés / interagis différemment (par exemple, gestion des erreurs, redirections, etc.). La beauté de cette approche était que vous pouvez par défaut les données, 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 Comme je le vois, vous rencontrerez le même problème à maintes reprises - où sont les données par défaut à vivre?

  • Si vous le stockez au niveau db / doctrine, que se passe-t-il si vous ne souhaitez pas stocker la valeur par défaut à chaque fois?
  • Si vous le stockez au niveau de l'entité, que se passe-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, est-ce évident lorsque vous en viendrez à maintenir le code plus tard?
  • 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, vous êtes allé trop loin - les données ne devraient pas être dans la vue, sans parler de JS (et nous ignorons la compatibilité, les erreurs de rendu, etc.)
  • Le service est excellent si comme moi vous l'utilisez à plusieurs endroits, mais c'est excessif pour 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 de formulaire d'inscription "newsletter" 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ées entre elles (par exemple, quels boutons radio dans différents types de formulaires étaient liés ensemble), j'ai utilisé des écouteurs d'événements. Lorsque j'ai construit une entité plus compliquée (par exemple, une entité qui nécessitait des enfants ou beaucoup de données par défaut), j'ai utilisé une fonction (par exemple, «getFactory») pour créer l'élément selon mes besoins.

Je ne pense pas qu'il y ait une «bonne» approche, car chaque fois que j'ai eu cette exigence, elle a été légèrement différente.

Bonne chance! J'espère que je vous ai donné matière à réflexion en tout cas et que je n'ai pas trop bavardé;)


Pourriez-vous donner un peu plus de détails sur ce que vous entendez par «un service qui a généré tous les formulaires»? Je travaille également sur un projet vraiment centré sur les formulaires en ce moment et ce serait formidable d'avoir des perspectives différentes à ce sujet.
user2268997

2
lors de l'utilisation de doctrine, les constructeurs ne sont pas appelés lorsqu'une entité est chargée à partir de la base de données.
NDM

43

Si vous devez définir la 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, myFieldalways sera défini sur la valeur par défaut, au lieu d'obtenir la valeur de l'entité.


Dans le cas de tableaux au lieu d'entités, remplacez simplement $options['data']->getMyField()par$option['data']['myField']
ggg

3
C'est le bon moyen pour ajouter / mettre à jour, je pense. Mais je déteste que Symfony le rende trop complexe.
Yarco

C'est la seule bonne réponse. Je ne comprends pas les autres réponses quand je regarde la doc. empty_data: Cette option détermine la valeur renvoyée par le champ lorsque la valeur soumise est vide. Il ne fixe pas de valeur initiale
Vincent Decaux

19

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 donne la possibilité de définir des valeurs initiales avec la méthode setData () . Le générateur de formulaire est passé à la méthode createForm () de votre classe de formulaire.

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


16

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 construct:

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

Même ainsi, votre formulaire peut avoir des champs supplémentaires non mappés à votre entité ( 'mapped' => false). Utilisez setData(...)pour cela.
Dizzley

12

Approche 1 (à partir 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 à partir 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 la valeur null que 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'
        )
    );
}

Le premier fonctionne (merci!), Le second ne fonctionne pas (pour moi): $ options ["data] est toujours défini, donc la valeur par défaut ne sera jamais utilisée. Je me demande toujours si la solution numéro 1 est la voie prévue pour le faire ...
herrjeh42

Vous avez raison sur le fait que $ options ['data'] est toujours défini. Si vous n'initialisez pas le champ d'entité, vous pouvez tester la valeur null sur le champ à la place, par exemple. 'data' => $ options ['data'] -> getColor ()! == null? etc ... Cela suppose que null n'est pas une valeur valide pour le champ de couleur, donc les entités existantes n'auraient jamais une valeur nulle pour ce champ.
crysallus

ah, stupide moi: je l'ai essayé avec 'isset ($ $ options [' data '] -> getColor ())', j'ai reçu un message d'erreur sur "l'utiliser dans des contextes d'écriture n'est pas autorisé" et j'ai oublié que je dois vérifiez-le différemment :-)
herrjeh42

1
En fait, il semble y avoir des occasions où l'entrée de données n'est pas définie. Plus sûr pour tester les deux ie isset ($ options ['data']) && $ options ['data'] -> getColor ()! == null? ...
crysallus

9

Vous pouvez définir une valeur par défaut, par exemple pour le formulaire 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();

Dans le cas où 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();

2
Je préfère cette méthode, d'autant plus que dans la plupart des applications, vous créez un formulaire et transmettez une entité que le formulaire traite.
skrilled le

9

Une solution générale pour tout cas / approche, principalement en utilisant un formulaire sans classe ou lorsque nous avons besoin d'accéder à n'importe quel service 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' defaultoption dans n'importe quel champ de formulaire:

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

Cela aurait dû être accepté comme la meilleure réponse (à jour)
medunes

7

N'utilisez pas:

'data' => 'Default value'

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

"L'option data remplace toujours la valeur extraite des données de 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 lui fait perdre sa valeur persistante lorsque le formulaire est soumis."


Utilisez le suivant:

Disons que, pour cet exemple, vous avez une entité Foo, et il y a un champ "actif" (dans cet exemple, CheckBoxType, mais le processus est le même pour tous les autres types), que vous voulez 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',
    ));
}

C'est de l'argent !! Utilisez l'écouteur d'événements de formulaire pour vérifier vos valeurs avant de les définir par défaut. Cela devrait être la réponse acceptée pour les valeurs par défaut dans vos formulaires, car elle fonctionne à la fois pour les nouvelles actions et les actions de modification.
tlorens

C'est la bonne façon de gérer cela et cela devrait être la réponse acceptée.
Bettinz

Ce que vous mentionnez au début n'est pas vrai si vous utilisez un conditionnel / ternaire. Comme ça:'data' => $data['myfield'] ?? 'Default value'
xarlymg89

6
->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));
     }

});

c'est une belle solution. Appeler $event->setData()au lieu de lire le champ pourrait le rendre encore meilleur.
user2268997

5

Ma solution:

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

4

Juste pour que je comprenne le problème.

Vous souhaitez ajuster la façon 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é existe, utilisez la valeur de la base de données.

Personnellement, je pense que la solution de @ MolecularMans est la voie à suivre. Je définirais en fait 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 accrochez un écouteur sur votre type de formulaire et vous pouvez ensuite examiner votre entité et ajuster le générateur-> ajouter des instructions en conséquence en fonction de la présence d'une entité nouvelle ou existante. Vous devez toujours spécifier vos valeurs par défaut quelque part bien que vous puissiez simplement les coder dans votre écouteur. Ou passez-les dans le type de formulaire.

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


4

Si vous utilisez un FormBuilderdans symfony 2.7 pour générer le formulaire, vous pouvez également passer les données initiales à la createFormBuilderméthode du contrôleur

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

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

3

Souvent, pour les valeurs par défaut de la forme, j'utilise des appareils. Bien sûr, cette manière n'est pas la plus simple, 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, le champ de type symfony a les données d' option .

Exemple

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

3

Il existe un moyen très simple, vous pouvez définir les valeurs 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

Si vous définissez «données» dans votre formulaire de création, cette valeur ne sera pas modifiée lors de l'édition 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.


Beaucoup plus utile qu'une réponse acceptée! Si vous utilisez PHP7 +, vous pouvez le rendre encore plus soigné avec:'data' => $data['myfield'] ?? 'Default value',
Boykodev

Vous avez une faute de frappe dans la fonction array_key_exists ()
Deadpool

1

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

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

cette approche fonctionne, mais présente l'inconvénient que vous devez le faire chaque fois que vous utilisez la classe de formulaire et elle est très détaillée (beaucoup d'instructions d'ensemble). Comme le composant de formulaire est très élégant, il doit y avoir autre chose. Mais merci quand même :-)
herrjeh42

@ jamie0726 À mon avis, c'est la responsabilité du contrôleur de définir les valeurs de l'objet chaque fois qu'il est nouveau ou récupéré. De cette façon, vous pouvez faire en sorte que le formulaire soit utilisé dans différentes situations avec différents comportements, par exemple, la nouvelle couleur peut changer car l'utilisateur a un rôle de gestionnaire ou de supermanager, et comme il s'agit d'une logique métier, cela devrait être contrôlé par le contrôleur ou un service, pas le formulaire. Donc, comme l'a déclaré Cerad, je préfère également cette solution. Vous pouvez toujours créer un service pour définir ces valeurs par défaut et dans le contrôleur, utiliser ce service en le maintenant DRY.
saamorim

C'est la solution que j'ai choisie, car elle correspond à la logique que je pense. Les contrôleurs générés ont différentes méthodes pour créer des formulaires EDIT et CREATE, et c'est là que je définis les données par défaut / initiales pour la nouvelle entité.
alumi

1

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

Un exemple:

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

1

Je ne fais généralement que définir 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 si vous mettez simplement à jour ceux existants.


Cela ne semble pas fonctionner lorsqu'un 'empty_data'rappel est utilisé pour autoriser les paramètres du constructeur sur l'entité.
NDM

1

Comme Brian l'a demandé:

empty_data semble définir le champ sur 1 uniquement lorsqu'il est soumis sans valeur. Qu'en est-il lorsque vous souhaitez que le formulaire affiche par défaut 1 dans l'entrée lorsqu'aucune valeur n'est présente?

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

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

0

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

->add('projectDeliveringInDays', null, [
    'attr' => [
          'min'=>'1',
          'value'=>'1'
          ]
     ])
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.