How do I add a custom options page to the panel?

It’s totally possible to do what you want but unfortunately it not documented anywhere. I’m using panel routes, modals, and forms, for an upcoming plugin update. The best way to learn how to use them is reading the Panel source code.

I’ll briefly try to explain the process:

Panel Routes

Use panel()->routes() to register routes:

<?php // site/plugins/plugin-name/routes.php

panel()->routes([
    [
        'pattern' => 'my/plugin/route',
        'method'  => 'GET|POST',
        'filter'  => 'auth',
        'action'  => 'PluginName\Controller::config'
    ]
]);

The route pattern will be automatically prefixed with panel/. You’ll find route examples at panel/app/config/routes.php.

Controllers

Although one could use modal and forms straight inside a route closure, using a controller makes it easier in my opinion. The controller needs to extend Kirby\Panel\Controllers\Base and implement the view and form methods.

<?php // site/plugins/plugin-name/controller.php

namespace PluginName;

class Controller extends \Kirby\Panel\Controllers\Base
{
    public function config()
    {
        $configuration = 'fetch configuration';

        $form = $this->form('config', compact('configuration'), function ($form) use ($configuration) {
            // this will be called only when the form POSTs to this action
            try {
                // save configuration…

                panel()->notify(':)');
            } catch (Exception $e) {
                panel()->alert('Something went wrong!');
            }

            panel()->redirect(); // go back to dashboard
        });

        return $this->modal('config', compact('configuration', 'form'));
    }

    public function form($id, $data = array(), $submit = null)
    {
        $file = kirby()->roots()->plugins() . DS . 'plugin-name' . DS . 'forms' . DS . $id . '.php';

        return panel()->form($file, $data, $submit);
    }

    public function view($file, $data = array())
    {
        return new View($file, $data);
    }
}

You can add as many methods as needed. You’ll find controller examples at panel/app/controllers.

Take a look at panel/app/src/panel/controllers/base.php to understand what the base controller does under the hood.

Forms

The form method tells the controller where to look for forms, in this case it’s a form folder inside the plugins folder: site/plugins/plugin-name/forms.

You’ll find many form examples at panel/app/forms, just copy one of those to site/plugins/plugin-name/forms/config.php and tweak it to your needs.

Views

You’ll need to create a class that extends Kirby\Panel\View to tell the controller where to look for views:

<?php // site/plugins/plugin-name/view.php

namespace PluginName;

class View extends \Kirby\Panel\View
{
    public function __construct($file, $data = [])
    {
        $this->_root = kirby()->roots()->plugins() . DS . 'plugin-name' . DS . 'views';
        $this->_file = $file;
        $this->_data = $data;
    }
}

In this case it’s a views folder inside the plugins folder: site/plugins/plugin-name/views. This is where you can put modal views:

<!-- site/plugins/plugin-name/views/config.php-->

<div class="modal-content modal-content-medium">
  <?php echo $form ?>
</div>

Note that we are passing the $form variable to this view on the controller config() method. You can pass more variables too.

Conclusion

Next up, let’s load these files:

<?php // site/plugins/plugin-name/plugin-name.php

load([
  'pluginname\\controller' => __DIR__ . DS . 'controller.php',
  'pluginname\\view'  => __DIR__ . DS . 'view.php'
]);

require 'routes.php';

I just copied these examples from my plugin (not releases yet) and changed them a bit. Let me know if something doesn’t work as expected.

8 Likes