0

I'm trying to create a Magento extension but I'm getting an issue when accessing a custom form for submitting a new entry. The grid for showing results works fine but clicking the add new button from the grid results in an error where it's looking for the form in the wrong place (not the extension directory). I'm obviously overlooking something but I have spend hours checking everthing. I really hope someone can help pinpoint this.

The error:

Exception #0 (Magento\Framework\Exception\LocalizedException): Invalid block type: Magento\Backend\Block\Adminhtml\Menu\Edit\Form
Exception #1 (ReflectionException): Class Magento\Backend\Block\Adminhtml\Menu\Edit\Form does not exist

Layout: \app\code\Vendor\Customizablemenus\view\adminhtml\layout\customizablemenus_menu_edit.xml .

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="editor"/>
    <head>
        <script src="Vendor_Customizablemenus::js/customizablemenus-admin.js" />
        <css src="Vendor_Customizablemenus::css/category-selector.css" />
        <css src="Vendor_Customizablemenus::css/spectrum.css" />
        <css src="Vendor_Customizablemenus::css/customizablemenus.css" />
    </head>
    <body>
        <referenceBlock name="menu">
            <action method="setActive">
                <argument name="itemId" xsi:type="string">Vendor_Customizablemenus::manager</argument>
            </action>
        </referenceBlock>
        <referenceContainer name="content">
            <block class="Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit" name="customizablemenus_menu_edit" />
        </referenceContainer>
        <referenceContainer name="left">
            <block class="Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit\Tabs" name="customizablemenus_menu_edit_tabs">
                <block class="Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit\Tab\Menu" name="customizablemenus_menu_edit_tab_menu" />
                <action method="addTab">
                    <argument name="name" xsi:type="string">main_section</argument>
                    <argument name="block" xsi:type="string">customizablemenus_menu_edit_tab_menu</argument>
                </action>
            </block>
        </referenceContainer>
    </body>
</page>

Controller: \app\code\Vendor\Customizablemenus\Controller\Adminhtml\Menu\Edit.php .

namespace Vendor\Customizablemenus\Controller\Adminhtml\Menu;

use Magento\Backend\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\Registry;

class Edit extends \Magento\Backend\App\Action
{
    /**
     * Core registry.
     *
     * @var Registry
     */
    protected $_coreRegistry = null;

    /**
     * Variable.
     *
     * @var PageFactory
     */
    protected $resultPageFactory;

    /**
     * Construct.
     *
     * @param Context     $context           Context.
     * @param PageFactory $resultPageFactory ResultPageFactory.
     * @param Registry    $registry          Registry.
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory,
        Registry $registry
    ) {
        $this->resultPageFactory = $resultPageFactory;
        $this->_coreRegistry = $registry;
        parent::__construct($context);
    }

    /**
     * {@inheritdoc}
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Vendor_Customizablemenus::manager');
    }

    /**
     * Init actions.
     *
     * @return \Magento\Backend\Model\View\Result\Page
     */
    protected function _initAction()
    {
        $resultPage = $this->resultPageFactory->create();
        return $resultPage;
    }

    /**
     * Edit Customizablemenus menu.
     *
     * @return \Magento\Backend\Model\View\Result\Page
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    public function execute()
    {
        $id = $this->getRequest()->getParam('menu_id');
        $model = $this->_objectManager->create(\Vendor\Customizablemenus\Model\Menu::class);

        if ($id) {
            $model->load($id);
            if (!$model->getId()) {
                $this->messageManager->addError(__('This menu no longer exists.'));
                $resultRedirect = $this->resultRedirectFactory->create();

                return $resultRedirect->setPath('*/*/');
            }
        }

        $data = $this->_objectManager->get(\Magento\Backend\Model\Session::class)->getFormData(true);
        if (!empty($data)) {
            $model->setData($data);
        }

        $this->_coreRegistry->register('customizablemenus_menu', $model);

        $resultPage = $this->_initAction();

        $resultPage->getConfig()->getTitle()->prepend(__('Menu Management'));
        $resultPage->getConfig()->getTitle()
            ->prepend($model->getId() ? sprintf(__('Edit Menu "%s"'), $model->getTitle()) : __('New Menu'));
        return $resultPage;
    }
}

Block: \app\code\Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit.php

namespace Vendor\Customizablemenus\Block\Adminhtml\Menu;

/**
 * Customizablemenus Admin Menu Page
 */
class Edit extends \Magento\Backend\Block\Widget\Form\Container
{

    /**
     * Variable.
     *
     * @var \Magento\Framework\Registry
     */
    protected $_coreRegistry = null;

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

    /**
     * Initialize customizablemenus menu edit block.
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_objectId = 'menu_id';
        $this->_blockMenu = 'Vendor_Customizablemenus';
        $this->_controller = 'adminhtml_menu';

        parent::_construct();

        if ($this->_isAllowedAction('Vendor_Customizablemenus::manager')) {
            $this->buttonList->update('save', 'label', __('Save Menu'));
            $this->buttonList->add(
                'saveandcontinue',
                [
                    'label' => __('Save and Continue Edit'),
                    'class' => 'save',
                    'data_attribute' => [
                        'mage-init' => [
                            'button' => [
                                'event' => 'saveAndContinueEdit',
                                'target' => '#edit_form'
                            ],
                        ],
                    ]
                ],
                -100
            );
        } else {
            $this->buttonList->remove('save');
        }

        if ($this->_isAllowedAction('Vendor_Customizablemenus::manager')) {
            $this->buttonList->update('delete', 'label', __('Delete Menu'));
        } else {
            $this->buttonList->remove('delete');
        }
    }

    /**
     * Prepare collection.
     *
     * @param string $resourceId Resource ID.
     *
     * @return bool
     */
    protected function _isAllowedAction($resourceId)
    {
        return $this->_authorization->isAllowed($resourceId);
    }

    /**
     * Getter of url for "Save and Continue" button.
     *
     * @return string
     */
    protected function _getSaveAndContinueUrl()
    {
        return $this->getUrl(
            '*/*/save',
            ['_current' => true, 'back' => 'edit', 'tab' => '{{tab_id}}']
        );
    }
}

Form:\app\code\Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit\Form.php .

namespace Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit;

/**
 * Adminhtml customizablemenus menu edit form block
 */
class Form extends \Magento\Backend\Block\Widget\Form\Generic
{
    /**
     * Prepare form.
     *
     * @return $this
     */
    protected function _prepareForm()
    {
        $form = $this->_formFactory->create(
            [
                'data' => [
                    'id' => 'edit_form',
                    'action' => $this->getUrl('*/*/save'),
                    'method' => 'post',
                    'enctype' => 'multipart/form-data',
                ],
            ]
        );
        $form->setUseContainer(true);
        $this->setForm($form);
        return parent::_prepareForm();
    }
}

Menu: app\code\Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit\Tab\Menu.php .

namespace Vendor\Customizablemenus\Block\Adminhtml\Menu\Edit\Tab;

use Magento\Backend\Block\Template\Context;
use Magento\Framework\Registry;
use Magento\Framework\Data\FormFactory;
use Magento\Store\Model\System\Store;
use Magento\Config\Model\Config\Structure\Element\Dependency\FieldFactory;

/**
 * Customizablemenus Menu form block
 */
class Menu extends \Magento\Backend\Block\Widget\Form\Generic implements \Magento\Backend\Block\Widget\Tab\TabInterface
{
    /**
     * Variable.
     *
     * @var FieldFactory
     */
    protected $fieldFactory;

    /**
     * Variable.
     *
     * @var Store
     */
    protected $systemStore;

    /**
     * Variable.
     *
     * @var Options
     */
    protected $customizablemenusHelper;

    /**
     * Construct.
     *
     * @param Context      $context          Context.
     * @param Registry     $registry         Registry.
     * @param FormFactory  $formFactory      Context.
     * @param Store        $systemStore      Systemstore.
     * @param FieldFactory $fieldFactory     FormFactory.
     * @param array        $data             Data.
     */
    public function __construct(
        Context $context,
        Registry $registry,
        FormFactory $formFactory,
        Store $systemStore,
        FieldFactory $fieldFactory,
        array $data = []
    ) {
        $this->_localeDate = $context->getLocaleDate();
        $this->systemStore = $systemStore;
        $this->fieldFactory = $fieldFactory;
        parent::__construct($context, $registry, $formFactory, $data);
    }

    /**
     * Prepare form.
     *
     * @return $this
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    protected function _prepareForm()
    {
        $model = $this->_coreRegistry->registry('customizablemenus_menu');
        $form = $this->_formFactory->create();
        $form->setHtmlIdPrefix('customizablemenus_');
        $dependenceBlock = $this->getLayout()
            ->createBlock(\Magento\Backend\Block\Widget\Form\Element\Dependence::class);
        $fieldMaps = [];

        $fieldset = $form->addFieldset(
            'general_fieldset',
            ['legend' => __('General')]
        );

        if ($model->getId()) {
            $fieldset->addField('menu_id', 'hidden', ['name' => 'menu_id']);
        }

        $fieldMaps['title'] = $fieldset->addField(
            'title',
            'text',
            [
            'name' => 'title',
            'label' => __('Title'),
            'title' => __('Title'),
            'required' => true,
            'class' => 'required-entry',
            ]
        );

        $fieldMaps['identifier'] = $fieldset->addField(
            'identifier',
            'text',
            [
            'name' => 'identifier',
            'label' => __('Identifier'),
            'title' => __('Identifier'),
            'note' => __('a unique identifier that is used to
                        inject the slide menu via XML'),
            'required' => true,
            'class' => 'required-entry validate-code',
            ]
        );

        $fieldMaps['is_active'] = $fieldset->addField(
            'is_active',
            'select',
            [
            'name' => 'is_active',
            'label' => __('Status'),
            'title' => __('Status'),
            'required' => true,
            'options' => $model->getAvailableStatuses()
            ]
        );

        if (!$this->_storeManager->isSingleStoreMode()) {
            $field = $fieldset->addField(
                'store_id',
                'multiselect',
                [
                'name' => 'stores[]',
                'label' => __('Store View'),
                'title' => __('Store View'),
                'required' => true,
                'values' => $this->systemStore
                            ->getStoreValuesForForm(false, true)
                ]
            );
            $renderer = $this
                ->getLayout()
                ->createBlock(\Magento\Backend\Block\Store\Switcher\Form\Renderer\Fieldset\Element::class);
            $field->setRenderer($renderer);
        } else {
            $fieldset->addField(
                'store_id',
                'hidden',
                [
                'name' => 'stores[]',
                'value' => $this->_storeManager->getStore(true)->getId()
                ]
            );
            $model->setStoreId($this->_storeManager->getStore(true)->getId());
        }

        foreach ($fieldMaps as $fieldMap) {
            $dependenceBlock->addFieldMap(
                $fieldMap->getHtmlId(),
                $fieldMap->getName()
            );
        }

        $mappingFieldDependence = $this->getMappingFieldDependence();

        foreach ($mappingFieldDependence as $dep) {
            $negative = isset($dep['negative']) && $dep['negative'];
            if (is_array($dep['fieldName'])) {
                foreach ($dep['fieldName'] as $fieldName) {
                    $dependenceBlock->addFieldDependence(
                        $fieldMaps[$fieldName]->getName(),
                        $fieldMaps[$dep['fieldNameFrom']]->getName(),
                        $this->getDependencyField($dep['refField'], $negative)
                    );
                }
            } else {
                $dependenceBlock->addFieldDependence(
                    $fieldMaps[$dep['fieldName']]->getName(),
                    $fieldMaps[$dep['fieldNameFrom']]->getName(),
                    $this->getDependencyField($dep['refField'], $negative)
                );
            }
        }

        $this->setChild('form_after', $dependenceBlock);

        $defaultData = [
            'is_active' => 1,
        ];

        if (!$model->getId()) {
            $model->addData($defaultData);
        }

        $form->setValues($model->getData());
        $this->setForm($form);

        return parent::_prepareForm();
    }

    /**
     * Get field dependencies.
     *
     * @param string $refField    Reference field for field dependency.
     * @param bool   $negative    Invert selection of reference.
     * @param string $separator   Field seperator.
     * @param string $fieldPrefix Field prefix.
     *
     * @return $this->fieldFactory
     */
    public function getDependencyField(
        $refField,
        $negative = false,
        $separator = ',',
        $fieldPrefix = ''
    ) {
        return $this->fieldFactory->create(
            ['fieldData' =>
                [
                'value' => (string) $refField,
                'negative' => $negative,
                'separator' => $separator
                ],
                'fieldPrefix' => $fieldPrefix
            ]
        );
    }

    /**
     * Get mapping of field dependencies.
     *
     * @return getMappingFieldDependence[] Array of field dependencies.
     */
    public function getMappingFieldDependence()
    {
        return [

        ];
    }

    /**
     * Prepare label for tab.
     *
     * @return \Magento\Framework\Phrase
     */
    public function getTabLabel()
    {
        return __('Menu Config');
    }

    /**
     * Prepare title for tab.
     *
     * @return \Magento\Framework\Phrase
     */
    public function getTabTitle()
    {
        return $this->getTabLabel();
    }

    /**
     * {@inheritdoc}
     */
    public function canShowTab()
    {
        return true;
    }

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

Route: app\code\Vendor\Customizablemenus\etc\adminhtml\routes.xml .

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="customizablemenus" frontName="customizablemenus">
            <module name="SolideWebservices_Customizablemenus" />
        </route>
    </router>
</config>
0

Ok, I have come to learn that this method is deprecated and I should use the uiComponent for forms. I refactored the extension and it's working now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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