147

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

Ondrej Slinták
  • 31,386
  • 20
  • 94
  • 126
  • 1
    yes, but the answers given in this question are not satisfying/do not work ... I will add an "Edit" to explain why :-) – herrjeh42 Aug 01 '13 at 11:17
  • It seems that the 'perfect' solution you are after is for a field to have a 'default_value' option. Thing is, [currently it does not](http://symfony.com/doc/current/reference/forms/types/form.html), so I don't think the perfect solution you are looking for currently exists. The only thing symfony provides (see the link) _is_ the data option. So the if-then is the only approach that I can see atm. Even if there was a 'default_value' option on the field itself, I imagine it would essentially do the same thing internally anyway. – crysallus Aug 06 '13 at 02:40
  • Also, I have made a correction to my answer in approach 2 as per my comments below it. If that fixes the syntax issue you mentioned in point 2, you might want to edit that comment out. Or let me know what the issue is, and I'll fix my answer. – crysallus Aug 06 '13 at 02:44
  • possible duplicate of [Set default values using form classes in Symfony 2](http://stackoverflow.com/questions/17986481/set-default-values-using-form-classes-in-symfony-2) –  May 11 '15 at 01:02
  • 1
    @Crone this question was asked 2 years earlier – Ondrej Slinták Feb 12 '16 at 00:05
  • 1
    @OndrejSlinták I didn't vote to close either as dupe, but FYI: it doesn't matter which one came first, *"[If the new question is a better question or has better answers, then vote to close the old one as a duplicate of the new one.](http://meta.stackexchange.com/a/147651/321521)"* – Jeff Puckett Jul 05 '16 at 19:08
  • People seem not be satisfied with the answers. It might be due to the vague question. What do you mean by default value? A value that is always used? A value that is used, if no other value is bound on submission? An initial value used in the view, when the form hasn't been submitted yet? I downvoted... I cannot understand how this has that many votes – fishbone Feb 21 '17 at 09:52

22 Answers22

118

you can set the default value with empty_data

$builder->add('myField', 'number', ['empty_data' => 'Default value'])
rkmax
  • 17,633
  • 23
  • 91
  • 176
  • 30
    Setting data is not setting the default. This answer is the correct one. – Alexei Tenitski Apr 03 '14 at 02:24
  • 11
    This appears to only set the field to 1 when it is submitted with no value. What about when you want the form to default to displaying 1 in the input when no value is present? – Brian May 14 '14 at 12:51
  • In my testing empty_data doesn't allow me to override the default value from a field submitted empty, e.g. if you want to save to the database as 0 instead of NULL. This bug is still outstanding as far as I can tell: https://github.com/symfony/symfony/issues/5906 – Chadwick Meyer Jul 17 '14 at 18:32
  • 1
    This doesn't address the question; 'empty_data' only saves the specified value after form submit if the field had an empty value. It doesn't set a default value for text form field... it doesn't touch the form field at all, that'll just show as empty. – SteveExdia May 10 '22 at 20:37
113

Can be use during the creation easily with :

->add('myfield', 'text', array(
     'label' => 'Field',
     'empty_data' => 'Default value'
))
webda2l
  • 6,686
  • 2
  • 26
  • 28
  • 12
    For Symfony 2.1 I needed to change the `'data'` key to `'value'` – Edd Nov 29 '12 at 09:17
  • 2
    @Edd are you sure? Just tried to put in `value` in Symfony 2.1.5-DEV- didn't work. But `data` worked just fine. – Darmen Amanbay Dec 16 '12 at 12:27
  • 179
    This does not only set a default value, it will also always force the value under any context. Not what I would call a "default value"... – Hubert Perron Apr 03 '13 at 18:25
  • 4
    I downvoted this solution as it is not a solution for the problem (as Hubert Perron mentioned above). I am trying to get a better solution in this post http://stackoverflow.com/questions/17986481/set-default-values-using-form-classes-in-symfony-2 – herrjeh42 Aug 01 '13 at 11:29
  • 2
    I asked the question again and got a remarkable answer: http://stackoverflow.com/questions/17986481/set-default-values-using-form-classes-in-symfony-2 – herrjeh42 Aug 28 '13 at 06:52
  • 13
    This is the initial value, the default value is `empty_data` – Pierre de LESPINAY Sep 28 '15 at 13:45
  • 4
    `data` is useless - it overwrites the saved value. `empty_data` doesn't show the value, it uses it on empty value submit and makes it impossible to save unchecked choices. – moldcraft Jul 20 '17 at 09:04
  • This is the same bad answer as rkmax's, as it answers a different question than what's asked. The question asks how to "set a default value for text form field", not how to "save a default value if the form text field is submitted as empty". 'empty_data' will address the latter (form submit), not the former (form load; it won't populate the empty field with a default value). – SteveExdia May 10 '22 at 20:39
65

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

stefancarlton
  • 1,717
  • 11
  • 12
  • could you give a little more detail on what you meant about 'a service which generated all the forms'?I'm also working on a really form centered project right now and it would be great to have different perspectives on it. – user2268997 Sep 17 '14 at 12:13
  • 2
    when using doctrine, constructors are not called when an entity is loaded from the db. – NDM May 13 '15 at 11:11
  • Your references are great but now I have to Google search them and hope I find what you're talking about... I request that you add the links citing the documentation or whatever source that you're getting the suggestion from, like with Form Events or Extended Forms. – SteveExdia May 10 '22 at 20:44
48

If you need to set default value and your form relates to the entity, then you should use following approach:

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

Otherwise, myField always will be set to default value, instead of getting value from entity.

Dmytro
  • 5,443
  • 2
  • 52
  • 50
  • In case of arrays instead of entities, just replace `$options['data']->getMyField()` with `$option['data']['myField']` – ggg Nov 29 '14 at 15:12
  • 4
    This is the right way for both add/update, I think. But I hate Symfony make it too much complex. – Yarco Jun 21 '17 at 09:34
  • 1
    This is the only good answer. I don't understand other answers when I look at the doc. `empty_data` : This option determines what value the field will return when the submitted value is empty. It does not set an initial value – Vincent Decaux Jun 19 '20 at 13:27
  • The code I'm looking at builds the form through Sonata FormMapper, and there's no $options var passed anywhere, so I don't know how to get what you're talking about here. – SteveExdia May 10 '22 at 20:46
19

You can set the default for related field in your model class (in mapping definition or set the value yourself).

Furthermore, FormBuilder gives you a chance to set initial values with setData() method. Form builder is passed to the createForm() method of your form class.

Also, check this link: http://symfony.com/doc/current/book/forms.html#using-a-form-without-a-class

Jakub Zalas
  • 35,761
  • 9
  • 93
  • 125
16

If your form is bound to an entity, just set the default value on the entity itself using the construct method:

public function __construct()
{
    $this->field = 'default value';
}
Richard Turner
  • 12,506
  • 6
  • 36
  • 37
Hubert Perron
  • 3,022
  • 5
  • 34
  • 28
  • Even so, your form can have additional fields not be mapped to your entity (`'mapped' => false`). Use `setData(...)` for these. – Dizzley Nov 16 '13 at 08:00
  • This only works when creating a new record, not when editing an existing one. The default property value is just completely ignored or not even checked when pulling up an Edit form. – SteveExdia May 10 '22 at 20:48
12

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

Simply set the default value in your entity, either in the variable declaration or the constructor:

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

or

class Entity {
    private $color;

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

Approach 2 from a comment in the above link, and also Dmitriy's answer (not the accepted one) from How to set default value for form field in Symfony2?

Add the default value to the data attribute when adding the field with the FormBuilder, adapted from Dmitriy's answer.

Note that this assumes that the property will and will only have the value null when it's a new, and not an existing, entity.

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'
        )
    );
}
Community
  • 1
  • 1
crysallus
  • 358
  • 3
  • 5
  • The first one works (thanks!), the second one does not (for me): $options["data] is always set, so the default value will never be used. I am still wondering if solution number 1 is the intended way to do it... – herrjeh42 Aug 01 '13 at 06:48
  • You're right about $options['data'] always being set. If you don't initialise the entity field, you could test for null on the field instead, eg. 'data' => $options['data']->getColor() !== null ? etc... That assumes that null is not a valid value for the color field, so existing entities would never have a null value for that field. – crysallus Aug 01 '13 at 07:10
  • ah, stupid me: I tried it with 'isset($ $options['data']->getColor())', I got an error message about "using it in writing contexts is not allowed" and forgot that I have to check it differently :-) – herrjeh42 Aug 01 '13 at 07:25
  • 1
    Actually there does seem to be occasions when the data entry isn't set. Safer to test for both i.e. isset($options['data']) && $options['data']->getColor() !== null ? ... – crysallus Aug 01 '13 at 07:32
10

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'));
yceruto
  • 9,230
  • 5
  • 38
  • 65
10

Don't use:

'data' => 'Default value'

Read here: https://symfony.com/doc/current/reference/forms/types/form.html#data

"The data option always overrides the value taken from the domain data (object) when rendering. This means the object value is also overriden when the form edits an already persisted object, causing it to lose its persisted value when the form is submitted."


Use the following:

Lets say, for this example, you have an Entity Foo, and there is a field "active" (in this example is CheckBoxType, but process is the same to every other type), which you want to be checked by default

In your FooFormType class add:

...
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',
    ));
}
Bettinz
  • 600
  • 5
  • 14
cure85
  • 441
  • 5
  • 6
  • This here is money!! Use the form event listener to check your values prior to defaulting them. This should be the accepted answer for defaulting values in your forms because it works for both New actions and Edit actions. – tlorens Jul 18 '18 at 11:45
  • This is the correct way to handle this and this should be the accepted answer. – Bettinz Mar 13 '19 at 13:50
  • What you mention at the beginning is not true if you use a conditional / ternary. Like this: ```'data' => $data['myfield'] ?? 'Default value'``` – xarlymg89 Feb 18 '20 at 12:05
9

You can set a default value, e.g. for the form message, like this:

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

In case your form is mapped to an Entity, you can go like this (e.g. default username):

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

$form = $this->createFormBuilder($user)
    ->add('username')
    ->getForm();
Gottlieb Notschnabel
  • 9,408
  • 18
  • 74
  • 116
  • 2
    I prefer this method, especially since in most applications you are creating a form and passing in an entity that the form deals with. – skrilled Apr 18 '14 at 22:58
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));
     }

});
tirenweb
  • 30,963
  • 73
  • 183
  • 303
5

My solution:

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

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.

Cerad
  • 48,157
  • 8
  • 90
  • 92
4

If you're using a FormBuilder in symfony 2.7 to generate the form, you can also pass the initial data to the createFormBuilder method of the Controler

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

$formBuilder = $this->createFormBuilder($values);
$formBuilder->add('name', 'text');
Bob
  • 2,430
  • 22
  • 27
4

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.

3

Often, for init default values of form i use fixtures. Of cause this way is not easiest, but very comfortable.

Example:

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

Yet, symfony type field have the option data.

Example

$builder->add('token', 'hidden', array(
    'data' => 'abcdef',
));
user987339
  • 10,519
  • 8
  • 40
  • 45
3

There is a very simple way, you can set defaults as here :

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

$form = $this->formfactory->createBuilder('form', $defaults)
->add('sortby','choice')
->add('category','choice')
->add('page','hidden')
->getForm();
Alsatian
  • 3,086
  • 4
  • 25
  • 40
1

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);
Molecular Man
  • 22,277
  • 3
  • 72
  • 89
  • this approach works, but has the disadvantage that you have to do it every time you use the form class & it is very verbose (lots of set statements). As the form component is very elegant, there must be something else. But thanks anyway :-) – herrjeh42 Aug 01 '13 at 06:46
  • @jamie0726 In my opinion is the controller responsibility to set the values of the object whenever it's new or fetched. That way you can have the form being used in different situations with different behaviors, for instance, the new color might change because of the user has a manager or a supermanager role, and since this is a business logic, that should be controlled by the controller or a service, not the form. So as Cerad stated, I also prefer this solution. You could always create a service to set those default values and in the controller use that service keeping it DRY. – saamorim Aug 08 '13 at 09:05
  • This is the solution I chose, because it fits the logic I think. The generated controllers have different methods for creating EDIT and CREATE forms, and those are where I set the default/initial data for new entity. – alumi Nov 02 '15 at 09:34
1

If that field is bound to an entity (is a property of that entity) you can just set a default value for it.

An example:

public function getMyField() {
    if (is_null($this->MyField)) {
        $this->setMyField('my default value');
    }
    return $this->MyField;
}
Andrew Starlike
  • 379
  • 4
  • 14
1

I usually just set the default value for specific field in my entity:

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

This will work for new records or if just updating existing ones.

matotej
  • 11
  • 1
  • This doesn't seem to work when `'empty_data'` is a callback is used to allow constructor params on the entity. – NDM May 13 '15 at 11:16
1

As Brian asked:

empty_data appears to only set the field to 1 when it is submitted with no value. What about when you want the form to default to displaying 1 in the input when no value is present?

you can set the default value with empty_value

$builder->add('myField', 'number', ['empty_value' => 'Default value'])
Ondrej Slinták
  • 31,386
  • 20
  • 94
  • 126
Snowirbis
  • 81
  • 1
  • 6
0

I solved this problem, by adding value in attr:

->add('projectDeliveringInDays', null, [
    'attr' => [
          'min'=>'1',
          'value'=>'1'
          ]
     ])
Kaxa
  • 515
  • 1
  • 6
  • 11