Sonataadminbundle: sonata_collection unable to add row via modal way

Created on 16 Dec 2016  Â·  37Comments  Â·  Source: sonata-project/SonataAdminBundle

Environment

Windows 10 - Chrome 54

Sonata packages

sonata-project/admin-bundle 3.10.0
sonata-project/block-bundle 3.2.0
sonata-project/cache 1.0.7
sonata-project/core-bundle 3.1.1
sonata-project/datagrid-bundle 2.2
sonata-project/doctrine-extensions 1.0.2
sonata-project/doctrine-orm-admin-bundle 3.1.1
sonata-project/easy-extends-bundle 2.1.10
sonata-project/exporter 1.7.0
sonata-project/google-authenticator 1.0.2
sonata-project/user-bundle 3.2.0

Symfony packages

symfony/monolog-bundle 2.12.0
symfony/phpunit-bridge v2.8.14
symfony/polyfill-apcu v1.3
symfony/polyfill-intl-icu v1.3.0
symfony/polyfill-mbstring v1.3.0
symfony/polyfill-php54 v1.3.0
symfony/polyfill-php55 v1.3.0
symfony/polyfill-php56 v1.3.0
symfony/polyfill-php70 v1.3.0
symfony/polyfill-util v1.3.0
symfony/security-acl v2.8.0
symfony/swiftmailer-bundle v2.4.0
symfony/symfony v2.8.14

PHP version

PHP 5.5.12

Subject

In my admin I have a OneToMany defined as it:

/**
 * @ORM\OneToMany(targetEntity="Module", mappedBy="sequence", cascade={"persist", "remove"})
 */
 private $modules;

And the inversed side:

/**
 * @ORM\ManyToOne(targetEntity="ModuleSequence", inversedBy="modules", cascade={"persist"}, fetch="LAZY")
 * @ORM\JoinColumn(name="sequence_id", referencedColumnName="id")
 */
protected $sequence;

In my admin class I defined the 'modules' field as it:


->add('modules', 'sonata_type_collection',array(
       'by_reference' => false
 ))

Finally in the ModuleSequence Entity here's the addModule method:

     /**
     * Add modules
     *
     * @param \AppBundle\Entity\Module $module
     * @return ModuleSequence
     */

    public function addModule(\AppBundle\Entity\Module $module)
    {
        $module->setSequence($this);
        $this->modules[] = $module;

        return $this;
    }

I have the "add" button, I get the modal, I fill it and validate. The Ajax request is sent into the profiler but no new row appear.

The 'sequence_id' is not set in the database and I don't know why...

When I use the 'inline' & 'table' options, the id is well set.

I think there is a bug here.

Most helpful comment

Here is the doc that should be improved IMO

Ok, added to my todo list :)

All 37 comments

When you use the profiler form to find your ajax request in it, is there anything interesting?

The POST request is OK (code 200)
All parameters are in the request body plus _xml_http_request: true param.
But there is no "sequence_id" in the body but it's seem normal as this sequence is not created yet...

So the request seems to be complete and correct.

Is addModule called?

Hum apparently no, I put some logs in addModule method but nothing is written in logs.

I also get a request to in the profiler that I have not mentioned:

admin/core/get-form-field-element?code=app.admin.module_sequence&elementId=s585446f43dd5b_modules&uniqid=s585446f43dd5b

Hum apparently no, I put some logs in addModule method but nothing is written in logs.

What about setModules ?

admin/core/get-form-field-element?code=app.admin.module_sequence&elementId=s585446f43dd5b_modules&uniqid=s585446f43dd5b

What controller does this map to? Can you link to it?

setModules is not call too

When I call the URL I get an empty page with:
image

When I click the link I'm redirected to sonata admin on module/create action

What controller does this map to?

What I meant by that is : "what happens when you run router:match with that url?"

The controller/action is: sonata.admin.controller.admin:retrieveFormFieldElementAction

Can you please link to it on github?

Hmmm… this method seems to retrieve a sub form corresponding to just one element of the object being edited. Probably it's the part that corresponds to the collection, hence the "add" button. I don't think this is where your new element should be saved. The POST makes more sense. That's the action you should debug.

Yes, the request list is:

GET admin/app/module/create?uniqid=s5854512577170&code=app.admin.module&pcode=app.admin.module_sequence&puniqid=s5854512530df4
=> Get the modal view

_* CLICK on add btn *_

POST admin/app/module/create?uniqid=s5854512577170
=> Create the module without sequence_id

POST admin/core/get-form-field-element?code=app.admin.module_sequence&elementId=s585446f43dd5b_modules&uniqid=s585446f43dd5b
=> probably try to get added row but, as there is no setted id => no new row

Create the module without sequence_id

I think you should first fix your model. Can a module really live without a sequence? If not, you should specify the join column as not nullable (there is a JoinColumn annotation I think).

When I use the 'inline' & 'table' options, the id is well set.

How can it be set if the sequence_id does not exist yet? Does all the form data get posted when you do that? That would explain how it would work.

Ok, constraint added, you're right.

So I get a NullContraintException with a stacktrace copied here: http://pastebin.com/MEWmD9YJ

I add the 'inline' & 'table' options and now I get the NullContraintException ... maybe I was wrong at the beginning inline editing is no working too :/

Ok so how is this supposed to work at all? I mean maybe the modules subform shouldn't even get displayed until the sequence is saved, right?

With the modal or inline way I get the form displayed but when I save, I get the exception (not sure to answer to your question...)

Sure, but why even display the modules subform when you are on the create action? It only makes sense on the edit action, right? Or mabye the constraint was a bad idea and things are supposed to get linked afterwards? Or maybe both ways work, it depends on what you want most : data integrity or user experience?

I have bad memory, but I think I hit that bug myself… and maybe several others. It would be great to make a cookbook article about this if we solve this. Here is a frenchman getting the same problem early may

In the app the classic use case is:

A user will create a module_sequence (let say a module is a game) that contains, for exemple, 3 modules.

So, to be more user friendly I tried to allow the user to create the sequence and the modules on the same page... but if you tell that's not possible, I can accept it ;)

So, to be more user friendly I tried to allow the user to create the sequence and the modules on the same page... but if you tell that's not possible, I can accept it ;)

Here is the thing, I don't even know, it would be great to dig a bit on the way, find out, and document. Let's gather all related issues.

Here is one : #4111

They are saying Sonata and Doctrine are saying it is each other's problem…

And another one, with the same solution… : https://github.com/sonata-project/SonataDoctrineORMAdminBundle/issues/50

Here is another one : http://stackoverflow.com/questions/21420380/entitys-id-of-parent-is-not-saved-in-a-onetomany-relationship-in-sonataadmin . Can you try the solution described here?

Well this one solved the problem into inline editing mode but not in the modal mode

linking to this one : #2890 Jesus… how deep does this go?

:)

So, I will keep this solution but, I think, we have pointed I real trouble with collection form type that need to be discuss by the Sonata Team ;)

Anyway, that a lot for your help :)

Anyway, that a lot for your help :)

If you want to repay me, please make a PR to document this (in the doctrine ORM bundle). @damienalexandre suggested it 4 years ago, but nobody reacted… would you be the awesome guy that breaks the circle?

So, I will keep this solution but, I think, we have pointed I real trouble with collection form type that need to be discuss by the Sonata Team ;)

Yeah… @sonata-project/contributors , thoughts on this?

Here is the doc that should be improved IMO

Ok, added to my todo list :)

@CyrilleGuimezanes @lalop , can you please make a docs PR ?

hello @greg0ire, I dig a little be more before editing the doc to understand what happens.
The issue seams coming from the symfony form https://github.com/sonata-project/SonataAdminBundle/blob/3.13.0/Controller/CRUDController.php#L255
When the form populate the new object it doesn't call setChildrend or 'addChild` so you can't give the child the parent id.
I don't know that much symfony's form component to understand if the issue is on symfony, sonata or doctrine.
I continue...

I don't have enought knowledge yet to understand why but this definitively fix the issue.
https://github.com/sonata-project/SonataDoctrineORMAdminBundle/issues/50#issuecomment-5872661

The parent Entity need to have an setChildren method and link each child to it parent and the field need to be define with by_reference false.

I'm ok to update the doc if you want.

I'm ok to update the doc if you want.

Please do, I'll help you complete it with an explanation if necessary :)

@greg0ire I think this example is way to complicated https://sonata-project.org/bundles/doctrine-orm-admin/3-x/doc/reference/form_field_definition.html#advanced-usage-one-to-many
It's a mix between one-to-many, many-to-many and entity's inheritage.
Can I rewrite it to only show a one-to-many example ?

It's a mix between one-to-many, many-to-many and entity's inheritage.

How so?

Can I rewrite it to only show a one-to-many example ?

I'm all for clearer docs so sure, go ahead!

Was this page helpful?
0 / 5 - 0 ratings