Backend popup from the side menu

the same way i can call an ajax handler from a list controller in the backend,
i’d like to do the same from a simple sidemenu

currently we can do this:

# _list_toolbar.php
<a href="#" data-control="popup" data-handler="onCreateForm" data-request-data="create_mode: 1" class="btn btn-primary oc-icon-plus">
<?= e(trans('backend::lang.form.create')) ?>
</a>

and I’d like to call an handler from a sidemenu defined in the plugin.yaml for instance

new_course:
                label: menu.new_course
                icon: icon-plus
                url: voilaah/skillup/courses/create

but here we can only specify a url, nothing else.

How could we do this ?

Hey @chris,

You can add attributes to the navigation item and manipulate them using JavaScript.

For example:

promotions:
    label: Promotions
    url: xyz/website/promotions
    icon: icon-shopping-cart
    attributes:
        data-request: onHandler

Then, in a JavaScript file that gets loaded:

$(function () {
    $('li.mainmenu-item[data-request]').on('click', function (e) {
        e.preventDefault(); // Prevent default click behavior

        var requestHandler = $(this).attr('data-request'); // Get the request handler name

        // Trigger an AJAX request using OctoberCMS framework
        $(this).request(requestHandler);
    });
});

This is a functional example that you can adapt as needed. If necessary, you can also override the modules\backend\layouts\_submenu_items.php partial.

Hi @apinard
thanks for the suggestion.
Sounds like it is worth trying it out.

Would there be a way to get an existing controller context so I can just reuse the ajax Handler and the context (formModel etc, …) as I want show a popup with a formWidget.

I am giving it a try today, and the markup created does not seem to be ok.

the data-handler is attach to the li instead of the anchor a , therefore no ajax called is initiated.

<li class="mainmenu-item  svg-icon-container" data-request="onCreateNewCourse">
            <a href="http://oc-skillup.test/admin/voilaah/skillup/courses">
                <span class="nav-icon"><i class=" icon-plus"></i>
    </span>
<span class="nav-label"> New Course</span>
    <span class="counter empty" data-menu-id="skillup/new_course"></span>
            </a>
        </li>

Hi @chris,

Yes that’s why you will need to add the js.

I dont see how I can inject a js file since this side menu can be called from “anywhere” in my plugin.
because it’s a link and not attached to a specific controller.

@chris beforeDisplay - October CMS

public function boot(){
        Event::listen('backend.page.beforeDisplay', function($controller, $action, $params) {
            $controller->addJs('/plugins/author/plugin/js/all-pages.js');
        });
  }

thanks @apinard that helps a lot

getting closer and closer.

new_course:
                label: menu.new_course
                icon: icon-plus
                attributes:
                    data-control: popup
                    data-request: onCreateCourseWizard
                    data-request-data: "create_mode: 1"
Event::listen('backend.page.beforeDisplay', function ($controller, $action, $params) {
            $controller->addJs('/plugins/voilaah/skillup/assets/js/backend/add_menu.js');
            $controller->addDynamicMethod('onCreateCourseWizard', function () {
                $coursesController = new Courses; // an internal plugin controller
                return $coursesController->index_onCreateForm();
            });
        });

the popup display the loader in loop and the form widget, which is build in the method index_onCreateForm that works fine when called from the list_toolbar, is not displayed in the popup.
no error, no log anywhere. What am I missing here ?

1 Like

Hi Chris! Change data-request to data-handler.

In my case everything works like this:

Plugin.php

            'sideMenu' => [
                'consumers_create' => [
                    'label' => 'New consumer',
                    'icon' => 'icon-plus',
                    'url' => Backend::url('my/app/consumers/create'),
                    'itemType' => 'primary',
                    'attributes' => ['data-handler' => 'onCreateForm', 'data-request-url' => Backend::url('my/app/consumers/create'), 'data-control' => 'popup', 'data-size' => '1400']
                ],

Consumers.php

    public function onCreateForm()
    {     
        $this->asExtension('FormController')->create();
        return $this->makePartial('create_form');
    }

Javascript not used.

I can create new consumers even from my Dashboard in popups.

1 Like

thanks @hauzmann you are right, changing data-request to data-handler works perfectly now.

2 Likes