Skip to content

[Form] Add "prototype_data" option to collection type #12314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

kgilden
Copy link
Contributor

@kgilden kgilden commented Oct 24, 2014

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #5095
License MIT
Doc PR symfony/symfony-docs#4367

Makes it possible to have default data for collection prototypes.

@kgilden kgilden changed the title [Form] Add "prototype_data" option to collection type [WIP][Form] Add "prototype_data" option to collection type Oct 24, 2014
@kgilden kgilden changed the title [WIP][Form] Add "prototype_data" option to collection type [Form] Add "prototype_data" option to collection type Oct 24, 2014
@kgilden
Copy link
Contributor Author

kgilden commented Oct 24, 2014

The failing test seems to be unrelated.

@linaori
Copy link
Contributor

linaori commented Oct 26, 2014

Maybe I'm mistaken, but isn't this already possible and done when creating the form?

@kgilden kgilden force-pushed the 5095-add-prototype-data branch from a85c9d1 to fc7b84c Compare October 27, 2014 09:44
@stof
Copy link
Member

stof commented Nov 21, 2014

@iltar this is about being able to initialize the prototype with a non-empty object, to have default values in fields.

@peterrehm
Copy link
Contributor

👍 Looks good.

@fabpot fabpot added the Form label Dec 7, 2014
@ghost
Copy link

ghost commented Jan 18, 2015

I hope this one can make 2.7!

@kgilden
Copy link
Contributor Author

kgilden commented Jan 18, 2015

@webmozart is there anything preventing this from making to 2.7?

@fabpot
Copy link
Member

fabpot commented Jan 18, 2015

👍

@stof
Copy link
Member

stof commented Jan 18, 2015

I don't think this is the right place to set the data in the prototype actually. It should be set when building the prototype instead

@stof
Copy link
Member

stof commented Jan 18, 2015

IMO, the implementation done in #6910 looked better

@peterrehm
Copy link
Contributor

I think either implementation is fine. @webmozart closed #6910 in favor of #9177. However it looks like #9177 is yet in a very early state. It will IMHO make sense to move ahead with this way if #9177 makes it into 3.0 it can still be adjusted.

I would agree that having the logic in buildForm() makes more sense than in buildView().

An option for 3.0 would be instantiate an entity as the prototype data as it works with an non embedded form by default. If you do not want this you can set the data as you want with the prototype_data option. I think this is normally the expected behavior but would break BC, therefore we can add this only in 3.0.

@backbone87
Copy link
Contributor

shouldnt this cause problems, when you provide data in the child options?
array('options' => array('data' => 'something'), 'prototype_data' => 'anotherthing')
since auto_initialize is true by default, as soon as the prototypes getForm method is called in the buildForm method, the prototypes data gets locked to something, and trying to setData afterwards should cause an exception to be thrown?

edit: #6910 does not have this problem, but another one: you cant provide prototype_data and item data at the same time, since the item data, will always overwrite the prototype_data

The "data" option under the "options" option intended for the target
form type would previously overwrite "prototype_data".
@kgilden
Copy link
Contributor Author

kgilden commented Jan 31, 2015

@peterrehm yep, instantiating an entity sounds the sanest way for me too. Presumably empty_data comes into action as well.

@backbone87 yes, You raise a very valid point. Do you mean this exception? I'll try whipping up a test to verify this.

Turns out my initial solution also suffered from item data always overwriting prototype data so I went for something closer to #6910. Now the data option under options will never be used for the prototype data, which is counter-intuitive anyway IMO.

Also, this PR should probably be merged to 2.7, which didn't exist back in October.

@backbone87
Copy link
Contributor

No i mean this exception: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Form.php#L314`
but you changed your PR now, so this issue should be solved.

Regarding inherit data check:
I cant come up with any sane use case to ever set inherit data = true in childs of a collection.

In my project i use the following check for prototype_data to be "injected" into the prototype:

$prototypeOptions = array_replace(array(
    'label' => $options['prototype_name'].'label__',
), $options['options']);

if($options['prototype_data'] !== null) {
    $prototypeOptions['data'] = $options['prototype_data'];
}

$prototype = $builder->create($options['prototype_name'], $options['type'], $prototypeOptions);
$builder->setAttribute('prototype', $prototype->getForm());

So if you use "prototype_data" = null (the default), it means "dont use any special prototype data" and the previous behavior is fully restored.

@backbone87
Copy link
Contributor

Regarding empty_data:
Sadly we cant reuse this, since we can not provide the same env for the closure call (we have no FormInterface that is in the correct state and viewData to pass as parameters to empty data closures)

@eXtreme
Copy link
Contributor

eXtreme commented Apr 15, 2015

Thanks @backbone87 that's a good tip, your solution works like a charm.

For anyone wanting "a ready to go" code, here's a form type extension I use:

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CollectionTypeExtension extends AbstractTypeExtension
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($options['allow_add'] && $options['prototype']) {
            $prototypeOptions = array_replace(array(
                'label' => $options['prototype_name'].'label__',
            ), $options['options']);

            if ($options['prototype_data'] !== null) {
                $prototypeOptions['data'] = $options['prototype_data'];
            }

            $prototype = $builder->create($options['prototype_name'], $options['type'], $prototypeOptions);
            $builder->setAttribute('prototype', $prototype->getForm());
        }
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array('prototype_data' => null));
    }

    public function getExtendedType()
    {
        return 'collection';
    }
}

Just register it in your services:

services:
    acme_demo_bundle.collection_type_extension:
        class: Acme\DemoBundle\Form\Extension\CollectionTypeExtension
        tags:
            - { name: form.type_extension, alias: collection }

and you can use collection form type type with new prototype_data option.

cheers 🍻

@webmozart
Copy link
Contributor

Thanks a lot for working on this @kgilden!

@peterrehm
Copy link
Contributor

👍 Awesome to get that supported by default.

@backbone87
Copy link
Contributor

@webmozart the way its currently implemented in this commit IS a BC break since the prototype_data will ALWAYS be used, even if legacy code not using prototype_data relies on the old behavior where the data option is used for the prototype form. i recommend revisiting this implementation and using code similar to the one i showed in my comment #12314 (comment)

@xabbuh
Copy link
Member

xabbuh commented Sep 6, 2015

@backbone87 Please open a new issue if you think you have found a bug/a BC break as your comment easily gets lost in an already closed pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants