Grid buttons action

Hi,

i’ve duplicated and customized a Monitor grid in a my .twig view and in a my controller OARemoteControlController:

function grid()
    {
        { ... }

        foreach ($displays as $display) {

            { ... }
            if ($this->getUser()->checkEditable($display)) {

                // Play Command
                $display->buttons[] = array(
                    'id' => 'button_play',
                    'url' => $this->urlFor('remoteControl.playCommand', ['id' => $display->displayId]),
                    'text' => __('Play')
                );
            }
        }
        
        { ... }
    }

    /** Send Test Command**/
    public function playCommand($displayId) {

        // Return
        $this->getState()->hydrate([
            'httpStatus' => 204,
            'message' => sprintf(__('Command Sent to %s'), $displayId->displayId),
            'id' => $displayId->displayId
        ]);

    }

and i have added a line in the routes.php file:

$app->get('/remoteController/:id', '\Xibo\Custom\OARemoteControlController:playCommand')->name('remoteControl.playCommand');

But When i click on the Play button it writes an Error Log:

[2016-08-12 15:14:27] WEB.ERROR: Problem with Template: View = remotecontrol-page [] {"uid":"038cdd1","method":"GET","route":"/remoteControl/view","userId":1} [2016-08-12 15:14:27] WEB.ERROR: Problem with Form Template Exception Type: Xibo\Exception\ControllerNotImplemented [] {"uid":"038cdd1","method":"GET","route":"/remoteControl/view","userId":1}

What does it mean?
What is the correct way to call a function of the same controller through a button ?

Thanks

Xibo assumes the default flow is Render Button → Render Form → Execute Form. It will therefore call XiboFormRender() JavaScript function on your link unless you specify the button is external by adding 'external' => true to the button array.

I don’t know where that is coming from - have you inspected the link on your button to make sure the URL is as you’d expect it to be?

Ok,

i have modified the button code adding the ‘external’ parameter:

function grid()
    {
        { ... }

        foreach ($displays as $display) {

            { ... }
            if ($this->getUser()->checkEditable($display)) {

                // Play Command
                $display->buttons[] = array(
                    'id' => 'displaygroup_button_play',
                    'action' => $this->playCommand($display->displayId),
                    'external' => true,
                    'text' => __('Play')
                );
            }
        }
        
        { ... }
    }

    /** Send Test Command**/
    public function playCommand($displayId) {

        // Return
        $this->getState()->hydrate([
            'httpStatus' => 204,
            'message' => sprintf(__('Command Sent to %s'), $displayId->displayId),
            'id' => $displayId->displayId
        ]);

    }

now the playCommand is called, but it refresh the page and i can’t see the notification message.

How can i show a simple notification to the user after the click button?

Thanks

I am not sure what you are doing there? The action should be the URL which you want assigned to the link - not the result of the play command method.

So you want to add a button to the row, which when clicked makes a request to the CMS and returns within the current CMS framework - i.e. interprets the response as if a form was used?

This should work:

// Play Command
$display->buttons[] = array(
    'id' => 'displaygroup_button_play',
    'action' => $this->urlFor('remoteControl.playCommand', ['id' => $display->displayId]),
    'class' => 'XiboAjaxSubmit',
    'text' => __('Play')
);

This will POST to the URL you’ve provided.


I thought you wanted a button that you would wire up yourself, completely independent of Xibo, which you can also do. You’d override the display-page.twig file and then instead of:

table.on('draw', dataTableDraw);

You’d provide your own function, which bound to your new button and took the appropriate action.

Hi Dan,

Thanks for your support.
I want to create a button that send to the player a predefined command like a PLAY, PAUSE etc…

This is my code modified like your suggestions:

// Play Command
                $display->buttons[] = array(
                    'id' => 'displaygroup_button_play',
                    'action' => $this->urlFor('remoteControl.playCommand', ['id' => $display->displayGroupId, 'command' => 'PLAY']),
                    'class' => 'XiboAjaxSubmit',
                    'text' => __('Play')
                );

And this is the playCommand function present in the same controller:

public function playCommand($displayGroupId, $command) {

        $displayGroup = $this->displayGroupFactory->getById($displayGroupId);

        if (!$this->getUser()->checkEditable($displayGroup))
            throw new AccessDeniedException();

        $displays = $this->displayFactory->getByDisplayGroupId($displayGroupId);

        $this->playerAction->sendAction($displays, $command);

        // Return
        $this->getState()->hydrate([
            'httpStatus' => 204,
            'message' => sprintf(__('Command Sent to %s'), $displayGroup->displayGroup),
            'id' => $displayGroup->displayGroupId
        ]);
    }

When i load the page in the CMS, it writes a log error:

[2016-08-18 08:17:28] WEB.ERROR: Named route not found for name: remoteControl.playCommand Exception Type: RuntimeException [] {"uid":"e00cbe0","method":"GET","route":"/remoteController","userId":1}

Where am I doing wrong?

You need to add a route for remoteControl.playCommand - remember we did that before in your custom Middleware?

You’re right, i added this row to my middleware:

$app->get('remoteControl/:id/:command', '\Xibo\Custom\OARemoteControlController:playCommand')->name('remoteControl.playCommand');

and the error disappears.

But if i click on the play button nothing appens…
Is there an error in my playCommand function?

Thanks

Try $app->post(

The request will be submitted via XHR - you can debug that (see the request and response) using your browsers developer tools.

Dan,

i modified my middleware in this way:

class OARemoteControlMiddleware extends Middleware
{
    public function call()
    {
        $app = $this->getApplication();

        // Register some new routes
        $app->get('/remoteControl/view', '\Xibo\Custom\OARemoteControlController:displayPage')->setName('remoteControl.view');
        $app->post('remoteControl/:id/:command', '\Xibo\Custom\OARemoteControlController:playCommand')->name('remoteControl.playCommand');
        // Register a new controller with DI
        // This Controller uses the CMS standard set of dependencies. Your controller can
        // use any dependencies it requires.
        // If you want to inject Factory objects, be wary of circular references.
        $app->container->singleton('\Xibo\Custom\OARemoteControlController', function($container) {
            return new \Xibo\Custom\OARemoteControlController(
                $container->logService,
                $container->sanitizerService,
                $container->state,
                $container->user,
                $container->helpService,
                $container->dateService,
                $container->configService,
                $container->store,
                $container->pool,
                $container->playerAction,
                $container->displayFactory,
                $container->displayGroupFactory,
                $container->displayEventFactory,
                $container->logFactory,
                $container->layoutFactory,
                $container->displayProfileFactory,
                $container->mediaFactory,
                $container->scheduleFactory
            );
        });

        // Next middleware
        $this->next->call();
    }
}

But it shows this error in the console browser:

Why it is calling the remoteControl/view instead of remoteControl/:id/:command ?

Can you inspect the link on the button to see what it is set to?

of course.

You’re missing a /

$app->post('/remoteControl/:id/:command', '\Xibo\Custom\OARemoteControlController:playCommand')->name('remoteControl.playCommand');

I’ve also no idea where in the thread this happened, but you’ve changed url to action:

'action' => $this->urlFor('remoteControl.playCommand', ['id' => $display->displayGroupId, 'command' => 'PLAY'])

should be

'url' => $this->urlFor('remoteControl.playCommand', ['id' => $display->displayGroupId, 'command' => 'PLAY'])
1 Like