Nested Relationships not working properly when using popup form

I have a TestModels controller for a TestModel model and this config_relation.yaml:

items:
    label: Items
    view:
        list: $/utopigs/content/models/testmodelitem/columns.yaml
        toolbarButtons: create|delete
    manage:
        form: $/utopigs/content/models/testmodelitem/fields.yaml
items[subitems]:
    label: Subitems
    view:
        list: $/utopigs/content/models/testmodelsubitem/columns.yaml
        toolbarButtons: create|delete
    manage:
        form: $/utopigs/content/models/testmodelsubitem/fields.yaml

TestModel fields.yaml:

fields:
    title:
        label: Title
    items:
        label: Items
        type: relation

TestModelItem fields.yaml:

fields:
    title:
        label: Title
    subitems:
        label: Subitems
        type: relation

If I setup TestModel as normal form, it works perfectly. But if I configure it as a popup form, when I try to create a new subitem (or update an existing one) I get this error:

“Relation behavior used in Utopigs\Content\Controllers\TestModels does not have a model defined.”

Is this a bug, or I am missing something?

Most probably you are missing something. It should work as expected.
I might be wrong, but there is an official test plugin where all the relations and functionality is tested and developed. Could be a good example for you to look at.

From what I see, you probably need:

cities:
            label: Cities
            type: partial
            path: field_cities
            tab: General

In your controller folder: _field_cities.htm

<?= $this->relationRender('cities') ?>

This should render a relation controller Popup style like. If that is what you mean.

I checked the test plugin, but this functionallity is not present there.

What I’m trying to use is:

  • form in a popup design instead of a page
  • in this form, a relationship + a nested relationship

I can’t see this behaviour in the test plugin. There are popup forms (in “plugins” controller) and nested relationships (in “cities” controller) but not both at the same time. This is the combination that is failing.

I created a very basic plugin demonstrating the bug

1 Like

Yeah, I’m pretty sure it’s a bug resp. an omission.

The page example works because the “root” model is initialised through the the record id in the update URL. But the information of the “form_record_id” is lost in nested relationship items and the relation chain does not contain information about the “super parent” model.

If found a workaround by forcing the controller into the correct context:

TestPopup Controller


    public function index()
    {
        parent::index();

        if (($recordId = post('form_record_id')) && post('_relation_field') === 'items[subitems]') {
            $this->dispatchBrowserEvent('backend:force-update-url', ['url' => $this->actionUrl('update', $recordId)]);
        } else {
            $this->dispatchBrowserEvent('backend:force-update-url', ['url' => $this->actionUrl('index')]);
        }
    }

    public function update()
    {
        parent::update($this->params[0]);

        $relationField = post('_relation_field');

        if (empty($relationField) || $relationField === 'items') {
            $this->dispatchBrowserEvent('backend:force-update-url', ['url' => $this->actionUrl('index')]);
        } else {
            $this->dispatchBrowserEvent(
                'backend:force-update-url',
                ['url' => $this->actionUrl('update', $this->params[0])]
            );
        }

        if ($relationField === 'items[subitems]') {
            $this->action = 'index';
        }
    }

testpopup/index.htm

<?= $this->listRender() ?>

<script>
    addEventListener('backend:force-update-url', function(event) {
        window.history.pushState(null, null, event.detail.url);
    })
</script>

More like a bit of fun, but if you need an urgent workaround, this could do it.

Do you want to open a Github issue? I’ll chime in with my findings.

I tried to work out a proper solution, but I am unsure how to tackle it. The main problem is imho, that the popup form design only works the first step down. After that, the process is taken over by the relation popup manager implementation, which looses the root model information since it relies on the record id in the URL.

Cheers
Marco

Thanks for the sample plugin, that was very useful.

I think I may have a viable fix for this coming in v4.1.9… it is based on Marco’s solution, except it just initializes the relation with an empty model instead of pulling it from the URL.

Nested Relations don’t really need to know the originating record (in most cases) and an empty one will initialize the relationship chain just fine.

Hopefully it helps.

1 Like