5

I created my custom module for backend, I created the controller, I added the link on standard menu and the acl configuration, all these part works fine.

Now I'm trying to add a tab list on the left with a simple form to allow one image upload. But I have some problem with the creation of the block in the tab panel.

Here my code:

<vendor>\<module>\Block\Adminhtml\StoreLocator\Edit.php

<?php

namespace <vendor>\<module>\Block\Adminhtml\StoreLocator;

use Magento\Backend\Block\Widget\Form\Container;

class Edit extends Container
{
/**
 * Core registry
 *
 * @var \Magento\Framework\Registry
 */
protected $_coreRegistry = null;

/**
 * @param \Magento\Backend\Block\Widget\Context $context
 * @param \Magento\Framework\Registry $registry
 * @param array $data
 */
public function __construct(
    \Magento\Backend\Block\Widget\Context $context,
    \Magento\Framework\Registry $registry,
    array $data = []
) {
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

/**
 * Department edit block
 *
 * @return void
 */
protected function _construct()
{
    $this->_objectId = 'entity_id';
    $this->_blockGroup = '<vendor>_<module>';
    $this->_controller = 'adminhtml_settings';

    parent::_construct();

    if ($this->_isAllowedAction('<vendor>_<module>::save')) {
        $this->buttonList->update('save', 'label', __('Salva impostazioni'));
        /*$this->buttonList->add(
            'saveandcontinue',
            [
                'label' => __('Salva e continua modifica'),
                'class' => 'save',
                'data_attribute' => [
                    'mage-init' => [
                        'button' => [
                            'event' => 'saveAndContinueEdit',
                            'target' => '#edit_form'
                        ],
                    ],
                ]
            ],
            -100
        );*/
    } else {
        $this->buttonList->remove('save');
    }
}

/**
 * Get header with Department name
 *
 * @return \Magento\Framework\Phrase
 */
public function getHeaderText()
{
    if ($this->_coreRegistry->registry('store_locator')->getId()) {
        return __("Modifica categorie ispirazione '%1'", $this->escapeHtml($this->_coreRegistry->registry('store_locator')->getTypeCode()));
    } else {
        return __('Modifica categorie ispirazione');
    }
}

/**
 * Check permission for passed action
 *
 * @param string $resourceId
 * @return bool
 */
protected function _isAllowedAction($resourceId)
{
    return $this->_authorization->isAllowed($resourceId);
}

/**
 * Getter of url for "Save and Continue" button
 * tab_id will be replaced by desired by JS later
 *
 * @return string
 */
protected function _getSaveAndContinueUrl()
{
    return $this->getUrl('setting/storelocator/save', ['_current' => true, 'back' => 'edit', 'active_tab' => '']);
}

}

Then my tab class:

<vendor>\<module>\Block\Adminhtml\StoreLocator\Edit\Tabs.php

<?php

namespace <vendor>\<module>\Block\Adminhtml\StoreLocator\Edit;

use Magento\Backend\Block\Widget\Tabs as WidgetTabs;

class Tabs extends WidgetTabs
{
/**
 * Class constructor
 *
 * @return void
 */
protected function _construct()
{
    parent::_construct();
    $this->setId('locator_edit_tabs');
    $this->setDestElementId('edit_form');
    $this->setTitle(__('Impostazioini pagina ispirazioni'));
}

/**
 * @return $this
 */
protected function _beforeToHtml()
{
    $this->addTab(
        'ispirazione',
        [
            'label' => __('Ispirazione'),
            'title' => __('Ispirazione'),
            'content' => $this->getLayout()->createBlock(
                '<vendor>\<module>\Block\Adminhtml\StoreLocator\Edit\Tab\StoreLocator'
            )->toHtml(),
            'active' => true
        ]
    );

    return parent::_beforeToHtml();
}
}

Then my form class:

<vendor>\<module>\Block\Adminhtml\StoreLocator\Edit\Form.php

<?php

namespace <vendor>\<module>\Block\Adminhtml\StoreLocator\Edit;

use \Magento\Backend\Block\Widget\Form\Generic;

class Form extends Generic
{
/**
 * @var \Magento\Store\Model\System\Store
 */
protected $_systemStore;

/**
 * @param \Magento\Backend\Block\Template\Context $context
 * @param \Magento\Framework\Registry $registry
 * @param \Magento\Framework\Data\FormFactory $formFactory
 * @param \Magento\Store\Model\System\Store $systemStore
 * @param array $data
 */
public function __construct(
    \Magento\Backend\Block\Template\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\Data\FormFactory $formFactory,
    \Magento\Store\Model\System\Store $systemStore,
    array $data = []
) {
    $this->_systemStore = $systemStore;
    parent::__construct($context, $registry, $formFactory, $data);
}

/**
 * Init form
 *
 * @return void
 */
protected function _construct()
{
    parent::_construct();
    $this->setId('locator_form');
    $this->setTitle(__('Impostazioini pagina ispirazioni'));
}

/**
 * Prepare form
 *
 * @return $this
 */
protected function _prepareForm()
{
    /** @var \Magento\Framework\Data\Form $form */
    $form = $this->_formFactory->create(
        [
            'data' => [
                'id' => 'edit_form',
                'action' => $this->getData('action'),
                'method' => 'post'
            ]
        ]
    );

    $form->setUseContainer(true);
    $this->setForm($form);

    return parent::_prepareForm();
}
}

Then here the class called on tabs part:

<vendor>\<module>\Block\Adminhtml\StoreLocator\Edit\Tab\StoreLocator.php

<?php

namespace <vendor>\<module>\Block\Adminhtml\StoreLocator\Edit\Tab;

use Magento\Backend\Block\Widget\Form\Generic;
use Magento\Backend\Block\Widget\Tab\TabInterface;

class StoreLocator extends Generic implements TabInterface
{

protected $_descriptionModel;

public function __construct(
    \Magento\Backend\Block\Template\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\Data\FormFactory $formFactory,
    \<vendor>\<module>\Model\StoreLocatorDescription $storeLocatorDescription,
    array $data = []
)
{
    parent::__construct($context, $registry, $formFactory, $data);
    $this->_descriptionModel = $storeLocatorDescription;
}

protected function _prepareForm()
{
    $form = $this->_formFactory->create();

    $fieldset = $form->addFieldset(
        'base_fieldset',
        [
            'legend' => __('Contenuto Store Locator'),
            'class' => 'fieldset-wide'
        ]
    );

    $fieldset->addField(
        'entity_id',
        'hidden',
        [
            'name' => 'entity_id'
        ]
    );

    $fieldset->addField(
        'description',
        'textarea',
        [
            'name' => 'description',
            'label' => __('Descrizione Store Locator'),
            'class' => 'txt-type',
            'title' => __('Descrizione Store Locator'),
            'required' => true,
            'note' => 'Inserisci la descrizione dello store locator da visualizzare nella home page.'
        ]
    );

    $fieldset->addField(
        'image_name',
        'image_name',
        [
            'title' => __('Immagine Store Locator'),
            'label' => __('Immagine Store Locator'),
            'name' => 'image_name',
            'note' => 'Formati immagini s: jpg, jpeg, png',
        ]
    );

    $this->setForm($form);
    return parent::_prepareForm();
}

/**
 * Return Tab label
 *
 * @return string
 * @api
 */
public function getTabLabel()
{
    return __('Ispirazione');
}

/**
 * Return Tab title
 *
 * @return string
 * @api
 */
public function getTabTitle()
{
    return __('Ispirazione');
}

/**
 * Can show tab in tabs
 *
 * @return boolean
 * @api
 */
public function canShowTab()
{
    return true;
}

/**
 * Tab is hidden
 *
 * @return boolean
 * @api
 */
public function isHidden()
{
    return false;
}
}

Finally the layout file:

<vendor>\<module>\view\adminhtml\layout\setting_storelocator_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-    2columns-left"    xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
<head>
    <title>
        Contenuto store locator
    </title>
</head>
<body>
    <referenceContainer name="left">
        <block class="<vendor>\<module>\Block\Adminhtml\StoreLocator\Edit\Tabs"
               name="store_locator.tabs"/>
    </referenceContainer>
    <referenceContainer name="content">
        <block class="<vendor>\<module>\Block\Adminhtml\StoreLocator\Edit" name="store_locator_edit"/>
    </referenceContainer>
</body>
</page>

I can't find what is wrong, but it doesn't work.

3

3 Answers 3

1

At a glance, in your <vendor>\<module>\view\adminhtml\layout\setting_storelocator_index.xml, I've noticed that your layout="admin- 2columns-left" has a lot of excessive space and after testing, I can safely say, you should change that to layout="admin-2columns-left" (i.e. remove the spaces)

That caused some unexpected behaviour in my test, that the menu block was being set to a boolean, thereby throwing an error when my Block was calling setActive. So the error message didn't help a whole lot, but I can now say that having spaces in your layout type causes interesting issues.

I hope this helps! Goodluck!

1

In the Edit Block you must correct the value of the variable:

$this->_controller = 'adminhtml_settings';

To:

$this->_controller = 'adminhtml_storeLocator';

And you should also remove blanks in layout="admin- 2columns-left"

0

you have to add or change $this->setDestElementId('edit_form'); inside _construct in your Tabs.php file if it is not present or wrong

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.