0

A custom module has Foo and Bar Models. In the Foo element's Form, there exists a grid listing of Bar items which belong to that Foo. This is an excerpt from the view/adminhtml/ui_component/bf_foo_form.xml file:

<insertListing name="bf_foo_form_bar_grid">
    <settings>
        <externalProvider>bf_foo_form_bar_grid.bf_foo_grid_data_source</externalProvider>
        <loading>false</loading>
        <autoRender>true</autoRender>
        <dataScope>bf_foo_form_bar_grid</dataScope>
        <ns>bf_foo_form_bar_grid</ns>
        <imports>
            <link name="foo_id">${ $.provider }:data.foo_id</link>
        </imports>
        <exports>
            <link name="foo_id">${ $.externalProvider }:params.foo_id</link>
        </exports>
    </settings>
</insertListing>

This is an excerpt from the view/adminhtml/ui_component/bf_foo_form_bar_grid.xml file where I try to add the Add new Bar button:

<settings>
    <spinner>listing_columns</spinner>
    <deps>
        <dep>bf_foo_form_bar_grid.bf_foo_grid_data_source</dep>
    </deps>
    <buttons>
        <button name="add">
            <url path="*/bar/new"/>
            <class>primary</class>
            <label translate="true">Add new Bar</label>
        </button>
    </buttons>
</settings>

As that code did not add the Add new Bar button, I tried another approach in the same view/adminhtml/ui_component/bf_foo_form_bar_grid.xml file:

<argument name="data" xsi:type="array">
    <item name="buttons" xsi:type="array">
        <item name="new_bar" xsi:type="array">
            <item name="name" xsi:type="string">new_bar</item>
            <item name="label" xsi:type="string">Add new Bar</item>
            <item name="class" xsi:type="string">secondary</item>
            <item name="url" xsi:type="string">*/bar/new</item>
        </item>
    </item>
</argument>

However, that did not work either! This is a screenshot of a Foo item, with a Bar item below, and the place where I'd like to add the Add new Bar button:

enter image description here

1 Answer 1

1

You can add button in fieldset before insertListing

app/code/Acme/Bar/view/adminhtml/ui_component/foo_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <!-- ... -->
    <fieldset name="...">
        <container name="button_set">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="formElement" xsi:type="string">container</item>
                    <item name="template" xsi:type="string">ui/form/components/complex</item>
                    <item name="label" xsi:type="null"/>
                </item>
            </argument>
            <container name="add_button" class="Acme\Bar\Ui\Component\Form\Url\AddNewFoo" component="Acme_Bar/js/form/element/link-button">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="formElement" xsi:type="string">container</item>
                        <item name="provider" xsi:type="null"/>
                        <item name="title" translate="true" xsi:type="string">Add New Bar</item>
                    </item>
                </argument>
            </container>
        </container>
        <insertListing name="bf_foo_form_bar_grid">
            <!-- ... -->
        </insertListing>
    </fieldset>
</form>

app/code/Acme/Bar/view/base/web/js/form/element/link-button.js

define([
    'jquery',
    'Magento_Ui/js/form/components/button',
    'Magento_Ui/js/modal/alert',
    'mage/translate',
], function ($, Button, alert, $t) {
    'use strict';

    return Button.extend({
        action: function() {
            if (this.href) {
                $('body').trigger('processStart');
                window.location.href = this.href;
            } else {
                alert({content: $t('No URL assigned')});
            }
        }
    });
});

app/code/Acme/Bar/Ui/Component/Form/Url/AddNewFoo

<?php
declare(strict_types=1);

namespace Acme\Bar\Ui\Component\Form\Url;

use Magento\Framework\UrlInterface;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Ui\Component\Form\Field;

class AddNewFoo extends Field
{
    protected UrlInterface $urlBuilder;

    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        UrlInterface $urlBuilder,
        array $components = [],
        array $data = []
    ) {
        parent::__construct($context, $uiComponentFactory, $components, $data);
        $this->urlBuilder = $urlBuilder;
    }

    public function prepare(): void
    {
        parent::prepare();

        $routePath   = '*/bar/new';
        $routeParams = [
            // optional current foo id
        ];

        $config = $this->getData('config');
        $config = array_merge($config, [
            'href' => $this->urlBuilder->getUrl($routePath, $routeParams),
        ]);

        $this->setData('config', $config);
    }
}
3
  • Perfect, thank you Victor! Answer accepted. Would you know how to redirect to the relevant Foo when saving?
    – dotancohen
    Commented Jul 11, 2022 at 8:07
  • 1. See comment optional current foo id, you can pass current foo into bar form, after into save action and after save redirect to foo edit page back by id Commented Jul 11, 2022 at 13:30
  • Yes, I did add the current foo_id there, and I use it to populate each Bar's foo_id field (read from the URL in Javascript). Thanks, I'll use save_after to redirect.
    – dotancohen
    Commented Jul 11, 2022 at 14:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.