Here’s a simple plugin with two tabs and two fields, one field per tab. This plugin was generated on https://pluginfactory.io/. It’s a great starting point to get the plugin scaffolding set up. After that I added the code that I’ve included below to get it to work.
It should give you something like the following screenshot for the first tab:
and for the second tab it should look similar to this:
Folder Structure
[-] craft
[-] plugins
[-] myplugin
[-] controllers
|-- MyPlugin_TabOneController.php
|-- MyPlugin_TabTwoController.php
[+] resources
[+] services
[-] templates
[-] _layouts
|-- cp.twig
[-] tabOne
|-- _index.twig
[-] tabTwo
|-- _index.twig
[+] translations
[+] variables
|-- MyPluginPlugin.php
myplugin/MyPluginPlugin.php
I'm only highlighting the functions that were necessary for the plugins to show up. Add or adjust them as needed.
...
public function registerCpRoutes()
{
return array(
'myplugin' => ['action' => "myPlugin/tabOne/index"],
'myplugin/additional-settings' => ['action' => "myPlugin/tabTwo/index"],
/**
* Each 'action' relates to a controller in your plugin.
* The names of your controller and these action must match.
*/
);
}
protected function defineSettings()
{
return array(
'someSetting' => array(AttributeType::String, 'label' => 'Some Setting', 'default' => ''),
'additionalSetting' => array(AttributeType::String, 'label' => 'Some Additional Setting', 'default' => ''),
/*...more settings here as needed...*/
);
}
public function getSettingsHtml()
{
return craft()->templates->render('myplugin/MyPlugin_Settings', array(
'settings' => $this->getSettings()
));
}
public function getSettingsUrl()
{
return 'myplugin';
/* This must be the same as the first segment in your cpRoutes. */
}
...
myplugin/controllers/MyPlugin_TabOneController.php
namespace Craft;
class MyPlugin_TabOneController extends BaseController
{
/**
* @var bool|array Allows anonymous access to this controller's actions.
* @access protected
*/
protected $allowAnonymous = array('actionIndex',
);
/**
*/
public function actionIndex()
{
$settings = craft()->plugins->getPlugin('myPlugin')->getSettings();
$this->renderTemplate('myplugin/tabOne/_index', array(
'settings' => $settings,
));
/**
* The path above is to your templates folder in your plugin.
*/
}
}
myplugin/controllers/MyPlugin_TabTwoController.php
namespace Craft;
class MyPlugin_TabTwoController extends BaseController
{
/**
* @var bool|array Allows anonymous access to this controller's actions.
* @access protected
*/
protected $allowAnonymous = array('actionIndex',
);
/**
*/
public function actionIndex()
{
$settings = craft()->plugins->getPlugin('myPlugin')->getSettings();
$this->renderTemplate('myplugin/tabTwo/_index', array(
'settings' => $settings,
));
/**
* The path above is to your templates folder in your plugin.
*/
}
}
myplugin/templates/_layouts/cp.twig
It’s not necessary to break out the templates like I have here but it does help to keep from repeating your self in the templates, especially if you have several tabs.
{% extends "_layouts/cp" %}
{% import "_includes/forms" as forms %}
{% includeCssResource "myplugin/css/Myplugin_Style.css" %}
{% includeJsResource "myplugin/js/Myplugin_Script.js" %}
{% set title = 'My Plugin' %}
{% set tabs = {
settings: { label: "Settings"|t, url: url('myplugin') },
additionalSettings: { label: "Additional Settings"|t, url: url('myplugin/additional-settings') },
} %}
myplugin/templates/tabOne/_index.twig
The data-saveshortcut
attribute on the form will allow you to use the keyboard shortcut to save your plugin’s settings by using ⌘ + S on a Mac. I’m assuming that Ctrl + S works on Windows although I haven’t tried it.
{% extends "myplugin/_layouts/cp" %}
{% import "_includes/forms" as forms %}
{% set selectedTab = 'settings' %}
{% set content %}
<h2>Settings</h2>
<form method="post" action="" accept-charset="UTF-8" data-saveshortcut data-confirm-unload>
{{ getCsrfInput() }}
<input type="hidden" name="action" value="plugins/savePluginSettings">
<input type="hidden" name="pluginClass" value="MyPlugin">
<input type="hidden" name="redirect" value="myplugin">
{{ forms.textField({
label: 'Some Setting',
instructions: 'Enter some setting here.',
id: 'settings-someSetting',
name: 'settings[someSetting]',
value: settings['someSetting']})
}}
<div class="buttons">
<input class="btn submit" type="submit" value="{{ 'Save'|t }}">
</div>
</form>
{% endset %}
myplugin/templates/tabOne/_index.twig
Notice that you’ll need to set the selectedTab
in each template for the tabs to work correctly. This should match one of your keys that was set in the tabs
variable in the myplugin/templates/_layouts/cp.twig
. Also the hidden redirect
input in the form should be set to wherever you want to it end up. I noticed that it felt the best when it went back to the original page and it showed the saved values.
{% extends "myplugin/_layouts/cp" %}
{% import "_includes/forms" as forms %}
{% set selectedTab = 'additionalSettings' %}
{% set content %}
<h2>Additional Settings</h2>
<form method="post" action="" accept-charset="UTF-8" data-saveshortcut data-confirm-unload>
{{ getCsrfInput() }}
<input type="hidden" name="action" value="plugins/savePluginSettings">
<input type="hidden" name="pluginClass" value="MyPlugin">
<input type="hidden" name="redirect" value="myplugin/additional-settings">
{{ forms.textField({
label: 'Some Additional Setting',
instructions: 'Enter some setting here.',
id: 'settings-additionalSetting',
name: 'settings[additionalSetting]',
value: settings['additionalSetting']})
}}
<div class="buttons">
<input class="btn submit" type="submit" value="{{ 'Save'|t }}">
</div>
</form>
{% endset %}
That should do it!