- Published on
How to add a slideout panel to your CraftCMS module or plugin
- Authors
- Name
- Leevi Graham
- @leevigraham
CraftCMS 3.7 added element editor slideouts. Craft 4 took it a step further with CpScreenSlideout
. I'm going to show you how to add slideouts to your own module or plugin.
Setup Craft
To get started you'll need:
- A CraftCMS v4.0.0 install
- A custom module or plugin.
Create a Module
Create a module following the CraftCMS docs.
Important: Double check that the module template root is registered in your module's init
method:
// Register Template Roots
Event::on(
View::class,
View::EVENT_REGISTER_CP_TEMPLATE_ROOTS,
function(RegisterTemplateRootsEvent $event) {
$event->roots[$this->id] = __DIR__ . '/templates';
}
);
Create an Asset Bundle
Create an Asset Bundle
following the CraftCMS docs.
Create a Control Panel Controller
If you're unfamiliar with Controllers
read the CraftCMS docs first.
We're going to create a new SlideoutController
that will be responsible for:
- Displaying the button to trigger the slideout
- Displaying the slideout content
- Processing the form submission in the slideout and returning data back to the element that triggered the slideout
Create the new SlideoutController
folders / files by running the following in your console or create them manually.
mkdir -p modules/controllers
touch modules/controllers/SlideoutController.php
Add an actionIndex
method to the SlideoutController.php
to render a control panel template with the following code:
<?php
namespace modules\controllers;
use craft\web\Controller;
use yii\web\Response;
class SlideoutController extends Controller
{
public function actionIndex(): Response
{
return $this->asCpScreen()
->title('Slideout Controller')
->contentTemplate(
'my-module/slideout/index.twig'
);
}
}
Create the template that's rendered in the indexAction
.
Run the following commands in your console or create the folder / file manually.
mkdir -p modules/templates/slideout
touch modules/templates/slideout/index.twig
Edit modules/templates/slideout/index.twig
add:
{{ _self }}
Test the SlideoutController:actionIndex
renders. Visit: https://your-site.com/admin?action=my-module/slideout/index
and you should see: my-module/slideout/index.twig
Trigger the slideout
To trigger a slideout there's a few steps:
- Create a new javascript widget in the
AssetBundle
- Load the
AssetBundle
in our CP screen - Add a button to our CP screen to trigger the slideout
- Create the slideout content action and template
- Test the Trigger Slideout button
Create a new javascript widget in the AssetBundle
The following javascript uses Craft's Garnish base class which is pretty much undocumented. Here's some other resources including a 2 hour hangout with Brandon Kelly walking through Craft's javascript.
Add the following javascript to your AssetBundle
script.js
:
(function ($) {
// Create a new object on the window we can call from our template
window.MyModuleSlideoutTrigger = Garnish.Base.extend({
// Called when a new widget is created
init: function (elementId) {
// Find the trigger element
this.$triggerElement = $('#' + elementId);
// Attach an onclick handler
this.$triggerElement.on('click', $.proxy(this, 'onClick'));
},
onClick: function () {
const slideout = new Craft.CpScreenSlideout('my-module/slideout/content');
// Open the slideout
slideout.open();
// Listen fro the submit event
slideout.on('submit', function (e) {
alert(JSON.stringify(e.response.data));
})
},
});
})(jQuery);
Load the AssetBundle
in our CP Screen
In the in the SlideoutController::indexAction
add:
Craft::$app->getView()->registerAssetBundle(Asset::class);
Your controller should now look like:
<?php
namespace modules\controllers;
use Craft;
use craft\web\Controller;
use modules\web\assets\cp\Asset;
use yii\web\Response;
class SlideoutController extends Controller
{
public function actionIndex(): Response
{
Craft::$app->getView()->registerAssetBundle(Asset::class);
return $this->asCpScreen()
->title('Slideout Controller')
->contentTemplate(
'my-module/slideout/index.twig'
);
}
}
Add a button to our CP screen to trigger the slideout
Edit modules/templates/slideout/index.twig
add a button and initialise the widget:
<button type="button" id="slideout-trigger" class="btn">
Trigger Slideout
</button>
{!-- Create a new widget instance and pass through the button ID --}
{% js %}
new MyModuleSlideoutTrigger('slideout-trigger');
{% endjs %}
Refresh the control panel and you should see:
Create the SlideoutController::actionContent
controller and template
Our javascript widget creates a new CpScreenSlideout
which loads it's content from a CP action so we need to create the new action and content template.
In the in the SlideoutController
add the new action code:
// Action: my-module/slideout/content
public function actionContent(): Response
{
// The slideout submits back to this action
// so check if it's a post and respond with a success
if($this->request->isPost) {
return $this->asSuccess('success');
}
// Return the slideout content in a <form>
// The form action points back to this controller action
return $this->asCpScreen()
->action('my-module/slideout/content')
->title('Slideout Content')
// Render the content template
->contentTemplate(
'my-module/slideout/content.twig'
);
}
Create the template that's rendered in the SlideoutController::contentAction
. Run the following commands in your console or create the folder / file manually.
mkdir -p modules/templates/slideout
touch modules/templates/slideout/content.twig
Edit modules/templates/slideout/content.twig
add:
{{ _self }}
Test the SlideoutController:actionContent
renders.
Visit: https://your-site.com/admin?action=my-module/slideout/index
and you should see a Save button and my-module/slideout/content.twig
Great… nearly there.
Test the Trigger Slideout button
Visit: https://your-site.com/admin?action=my-module/slideout/index
and click the "Trigger Slideout" button.
If everything works as expected you should see:
Wrapping Up
CraftCMS Slideout panels provide another tool in your module UI toolbelt.
I've shown you how to implement a Craft.CpScreenSlideout
but there's also Craft.Slideout
(the base class) and ElementEditorSlideout
which extends Craft.CpScreenSlideout
for editing elements.