Question

I've created a grid under a tab in an admin UI form. But I'm having trouble saving the checkbox change values.

enter image description here

I can't catch the tab checkbox values on form submit in the controller. Only the values from the top tab come through (this is a ui form).

Any ideas?

UI XML code

https://github.com/DominicWatts/Announce/blob/develop/view/adminhtml/ui_component/xigen_announce_group_form.xml#L42-L50

    <htmlContent name="announce_group_edit_tab_view_message_content">
        <block class="Xigen\Announce\Block\Adminhtml\Group\Edit\Tab\Tab" name="announce_group_edit_tab_message" template="Xigen_Announce::tab/message.phtml">
            <block class="Xigen\Announce\Block\Adminhtml\Group\Edit\Tab\Message" name="announce_group_edit_tab_message_grid" />
            <arguments>
                <argument name="sort_order" xsi:type="number">100</argument>
                <argument name="tab_label" xsi:type="string" translate="true">Messages</argument>
            </arguments>
        </block>
    </htmlContent>

Grid code

https://github.com/DominicWatts/Announce/blob/develop/Block/Adminhtml/Group/Edit/Tab/Message.php

<?php

declare(strict_types=1);

namespace Xigen\Announce\Block\Adminhtml\Group\Edit\Tab;

use Magento\Backend\Block\Template\Context;
use Magento\Backend\Block\Widget\Grid\Extended as ExtendedGrid;
use Magento\Backend\Block\Widget\Tab\TabInterface;
use Magento\Backend\Helper\Data;
use Magento\Framework\Registry;
use Xigen\Announce\Api\Data\GroupInterface;
use Xigen\Announce\Model\ResourceModel\Message\CollectionFactory;

class Message extends ExtendedGrid implements TabInterface
{
    /**
     * @var Registry
     */
    protected $coreRegistry = null;

    /**
     * @var bool
     */
    protected $isAjaxLoaded = true;

    /**
     * @var \Xigen\Announce\Model\ResourceModel\Message\CollectionFactory
     */
    protected $messageCollectionFactory;

    public function __construct(
        Context $context,
        Data $backendHelper,
        CollectionFactory $messageCollectionFactory,
        Registry $coreRegistry,
        array $data = []
    ) {
        $this->messageCollectionFactory = $messageCollectionFactory;
        $this->coreRegistry = $coreRegistry;
        parent::__construct($context, $backendHelper, $data);
    }

    /**
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setId('announce_group_edit_tab_message_grid');
        $this->setDefaultSort('message_id');
        $this->setDefaultDir('DESC');
        $this->setTitle(__('Messages'));
        $this->setSaveParametersInSession(true);
        $this->setUseAjax(true);
        if ($groupId = $this->getRequest()->getParam('group_id')) {
            $this->setDefaultFilter(['group_id' => $groupId]);
        }
        if ($this->canShowTab()) {
            $this->setDefaultFilter(['in_messages' => 1]);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getTabLabel()
    {
        return __('Messages');
    }

    /**
     * {@inheritdoc}
     */
    public function getTabTitle()
    {
        return __('Messages');
    }

    /**
     * {@inheritdoc}
     */
    public function isHidden()
    {
        return false;
    }

    /**
     * @return Grid
     */
    protected function _prepareCollection()
    {
        $collection = $this->messageCollectionFactory->create()
            ->addFieldToSelect("*");
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

    /**
     * @return Extended
     */
    protected function _prepareColumns()
    {
        $this->addColumn(
            'in_messages',
            [
                'type' => 'checkbox',
                'name' => 'in_messages',
                'values' => $this->_getSelectedMessages(),
                'align' => 'center',
                'index' => 'message_id',
                'header_css_class' => 'col-select',
                'column_css_class' => 'col-select'
            ]
        );

        $this->addColumn(
            'message_id',
            [
                'header' => __('Message Id'),
                'sortable' => true,
                'index' => 'message_id',
                'header_css_class' => 'col-id',
                'column_css_class' => 'col-id'
            ]
        );

        $this->addColumn(
            'name',
            [
                'header' => __('name'),
                'sortable' => true,
                'index' => 'name',
                'header_css_class' => 'col-name',
                'column_css_class' => 'col-name'
            ]
        );

        $this->addColumn(
            'status',
            [
                'header' => __('Status'),
                'align' => 'center',
                'filter' => \Xigen\Announce\Block\Adminhtml\Group\Edit\Tab\Grid\Filter\Status::class,
                'index' => 'status',
                'renderer' => \Xigen\Announce\Block\Adminhtml\Group\Edit\Tab\Grid\Renderer\Status::class
            ]
        );

        $this->addColumn(
            'sort',
            [
                'header' => __('Sort'),
                'type' => 'number',
                'validate_class' => 'validate-number',
                'index' => 'sort',
                'editable' => true,
                'edit_only' => true,
                'header_css_class' => 'col-sort',
                'column_css_class' => 'col-sort'
            ]
        );

        // $this->addExportType('*/*/exportCsv', __('CSV'));
        // $this->addExportType('*/*/exportExcel', __('Excel XML'));

        return parent::_prepareColumns();
    }

    /**
     * Add filter
     *
     * @param Column $column
     * @return $this
     */
    protected function _addColumnFilterToCollection($column)
    {
        // Set custom filter for in message flag
        if ($column->getId() == 'in_messages') {
            $messageIds = $this->_getSelectedMessages();
            if (empty($messageIds)) {
                $messageIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('message_id', ['in' => $messageIds]);
            } else {
                if ($messageIds) {
                    $this->getCollection()->addFieldToFilter('message_id', ['nin' => $messageIds]);
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }

    /**
     * @inheritdoc
     */
    public function canShowTab()
    {
        return $this->coreRegistry->registry('xigen_announce_group');
    }

    /**
     * Tab should be loaded through Ajax call
     * @return bool
     */
    public function isAjaxLoaded()
    {
        return false;
    }

    /**
     * Checks when this block is readonly
     * @return bool
     */
    public function isReadonly()
    {
        return false;
    }

    /**
     * Retrieve selected related messages
     * @return array
     */
    protected function _getSelectedMessages()
    {
        return array_keys($this->getSelectedMessages());
    }

    /**
     * Retrieve related message
     * @return array
     */
    public function getSelectedMessages()
    {
        $messages = [];

        if ($selected = $this->coreRegistry->registry('xigen_announce_group')) {
            $collection = $selected->getMessages();
        } elseif ($groupId = $this->getRequest()->getParam('group_id')) {
            $collection = $this->messageCollectionFactory->create()
                ->addFieldToSelect("*")
                ->addFieldToFilter(GroupInterface::GROUP_ID, ['eq' => $groupId]);
        }

        foreach ($collection as $item) {
            $messages[$item->getMessageId()] = ['sort' => $item->getSort()];
        }

        return $messages;
    }

    /**
     * @return string
     */
    public function getGridUrl()
    {
        return $this->getUrl('*/*/grid', ['_current' => true]);
    }

    /**
     * get row url
     * @param  object $row
     * @return string
     */
    public function getRowUrl($row)
    {
        return $this->getUrl(
            '*/message/edit',
            ['message_id' => $row->getId()]
        );
    }
}

In the controller I'm var dumping

var_dump($this->getRequest()->getPostValue());
var_dump($this->getRequest()->getParams());

But nothing for this tab. Until I catch the checkbox values I can't save changes.

Was it helpful?

Solution

You need to do some changes and corrections.

Edit view/adminhtml/ui_component/xigen_announce_group_form.xml file and put some extra code under announce_group_edit_tab_message as per below.

    <block class="Xigen\Announce\Block\Adminhtml\Group\Edit\Tab\Tab" name="announce_group_edit_tab_message" template="Xigen_Announce::tab/message.phtml">
        <block class="Xigen\Announce\Block\Adminhtml\Group\Edit\Tab\Message" name="announce_group_edit_tab_message_grid" />
        <arguments>
            <argument name="sort_order" xsi:type="number">100</argument>
            <argument name="tab_label" xsi:type="string" translate="true">Messages</argument>
        </arguments>
        <block class="Magento\Backend\Block\Widget\Grid\Serializer" name="customerproduct_grid_serializer">
            <arguments>
                <argument name="grid_block" xsi:type="string">announce_group_edit_tab_message_grid</argument>
                <argument name="callback" xsi:type="string">_getSelectedMessages</argument>
                <argument name="input_element_name" xsi:type="string">messages_list</argument>
                <argument name="reload_param_name" xsi:type="string">in_messages</argument>
            </arguments>
        </block>
        <block name="grid_script_js" template="Xigen_Announce::script-js.phtml"/>
    </block>

Now you need to change the method public from protected.

    public function _getSelectedMessages() {
          return array_keys($this->getSelectedMessages());
    }

We need to add a custom template file script-js.phtml to add an input field under POST data.

<script>
    require(["jquery"], function($){ $("input[name='messages_list']").attr('data-form-part','xigen_announce_group_form'); });
</script>

You may need to work on post data because it will send data like "1&2&3".

OTHER TIPS

  1. in your block template, you may create a hidden field (see /vendor/magento/module-catalog/view/adminhtml/templates/catalog/category/edit/assign_products.phtml for an example of what I mean)

  2. then, very much like this template above shows, add a javascript snippet that may behave similarly to /vendor/magento/module-catalog/view/adminhtml/web/catalog/category/assign-products.js. particularly, the line gridJsObject.rowClickCallback = categoryProductRowClick; and $('in_category_products').value = Object.toJSON(categoryProducts); may be most useful

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top