How to set default value for form field in Symfony2?

后端 未结 22 1294
暖寄归人
暖寄归人 2020-11-27 13:23

Is there an easy way to set a default value for text form field?

相关标签:
22条回答
  • 2020-11-27 13:33

    A general solution for any case/approach, mainly by using a form without a class or when we need access to any services to set the default value:

    // 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;
        }
    }
    

    and register the form extension:

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

    After that, we can use default option in any form field:

    $formBuilder->add('user', null, array('default' => $this->getUser()));
    $formBuilder->add('foo', null, array('default' => 'bar'));
    
    0 讨论(0)
  • 2020-11-27 13:33

    If you set 'data' in your creation form, this value will be not modified when edit your entity.

    My solution is :

    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',
        ));
    }
    

    Bye.

    0 讨论(0)
  • 2020-11-27 13:34

    Just so I understand the problem.

    You want to adjust the way the form is built based on data in your entity. If the entity is being created then use some default value. If the entity is existing use the database value.

    Personally, I think @MolecularMans's solution is the way to go. I would actually set the default values in the constructor or in the property statement. But you don't seem to like that approach.

    Instead you can follow this: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html

    You hang a listener on your form type and you can then examine your entity and adjust the builder->add statements accordingly based on havine a new or existing entity. You still need to specify your default values somewhere though you could just code them in your listener. Or pass them into the form type.

    Seems like a lot of work though. Better to just pass the entity to the form with it's default values already set.

    0 讨论(0)
  • 2020-11-27 13:34

    Default values are set by configuring corresponding entity. Before binding the entity to form set its color field to "#0000FF":

    // controller action
    $project = new Project();
    $project->setColor('#0000FF');
    $form = $this->createForm(new ProjectType(), $project);
    
    0 讨论(0)
  • 2020-11-27 13:39

    you can set the default value with empty_data

    $builder->add('myField', 'number', ['empty_data' => 'Default value'])
    
    0 讨论(0)
  • 2020-11-27 13:40

    I've contemplated this a few times in the past so thought I'd jot down the different ideas I've had / used. Something might be of use, but none are "perfect" Symfony2 solutions.

    Constructor In the Entity you can do $this->setBar('default value'); but this is called every time you load the entity (db or not) and is a bit messy. It does however work for every field type as you can create dates or whatever else you need.

    If statements within get's I wouldn't, but you could.

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

    Factory / instance. Call a static function / secondary class which provides you a default Entity pre-populated with data. E.g.

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

    Not really ideal given you'll have to maintain this function if you add extra fields, but it does mean you're separating the data setters / default and that which is generated from the db. Similarly you can have multiple getFactories should you want different defaulted data.

    Extended / Reflection entities Create a extending Entity (e.g. FooCreate extends Foo) which gives you the defaulted data at create time (through the constructor). Similar to the Factory / instance idea just a different approach - I prefer static methods personally.

    Set Data before build form In the constructors / service, you know if you have a new entity or if it was populated from the db. It's plausible therefore to call set data on the different fields when you grab a new entity. E.g.

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

    Form Events When you create the form you set default data when creating the fields. You override this use PreSetData event listener. The problem with this is that you're duplicating the form workload / duplicating code and making it harder to maintain / understand.

    Extended forms Similar to Form events, but you call the different type depending on if it's a db / new entity. By this I mean you have FooType which defines your edit form, BarType extends FooType this and sets all the data to the fields. In your controller you then simply choose which form type to instigate. This sucks if you have a custom theme though and like events, creates too much maintenance for my liking.

    Twig You can create your own theme and default the data using the value option too when you do it on a per-field basis. There is nothing stopping you wrapping this into a form theme either should you wish to keep your templates clean and the form reusable. e.g.

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

    JS It'd be trivial to populate the form with a JS function if the fields are empty. You could do something with placeholders for example. This is a bad, bad idea though.

    Forms as a service For one of the big form based projects I did, I created a service which generated all the forms, did all the processing etc. This was because the forms were to be used across multiple controllers in multiple environments and whilst the forms were generated / handled in the same way, they were displayed / interacted with differently (e.g. error handling, redirections etc). The beauty of this approach was that you can default data, do everything you need, handle errors generically etc and it's all encapsulated in one place.

    Conclusion As I see it, you'll run into the same issue time and time again - where is the defaulted data to live?

    • If you store it at db/doctrine level what happens if you don't want to store the default every time?
    • If you store it at Entity level what happens if you want to re-use that entity elsewhere without any data in it?
    • If you store it at Entity Level and add a new field, do you want the previous versions to have that default value upon editing? Same goes for the default in the DB...
    • If you store it at the form level, is that obvious when you come to maintain the code later?
    • If it's in the constructor what happens if you use the form in multiple places?
    • If you push it to JS level then you've gone too far - the data shouldn't be in the view never mind JS (and we're ignoring compatibility, rendering errors etc)
    • The service is great if like me you're using it in multiple places, but it's overkill for a simple add / edit form on one site...

    To that end, I've approached the problem differently each time. For example, a signup form "newsletter" option is easily (and logically) set in the constructor just before creating the form. When I was building forms collections which were linked together (e.g. which radio buttons in different form types linked together) then I've used Event Listeners. When I've built a more complicated entity (e.g. one which required children or lots of defaulted data) I've used a function (e.g. 'getFactory') to create it element as I need it.

    I don't think there is one "right" approach as every time I've had this requirement it's been slightly different.

    Good luck! I hope I've given you some food for thought at any rate and didn't ramble too much ;)

    0 讨论(0)
提交回复
热议问题