2

I would like to add tabs in setting page in my plugin. I have the following code in /[myplugin]/templates/_setting.html. However, the tabs do not show up, does anyone have any sample code to set up the tabs? Thanks

{% import "_includes/forms" as forms %}

{% set tabs = {
customer: { label: "Customer"|t, url: url('emailUser/_settings') },
veterinarian:    { label: "Veterinarian"|t, url: url('emailUser/_vetSettings') }
} %}

{{ forms.textField({
label: "Customer Account Creation Confirmation Subject"|t,
instructions: "Customer Account Creation Confirmation Subject" |t,
name: 'custAccountCreationSubject',
value: settings.custAccountCreationSubject,
})}}

{{ forms.textareaField({
label: "Customer Account Creation Confirmation Message"|t,
instructions: "Customer email message when customer register" |t,
name: 'custAccountCreation',
value: settings.custAccountCreation,
rows:10,
})}}

In myplugin.php

public function getSettingsHtml()
{
    return craft()->templates->render('emailuser/_settings',array(
                'settings'=>$this->getSettings()
    ));
}
7

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:

First tab of plugin

and for the second tab it should look similar to this:

Second tab of plugin

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!

  • the return for getSettingsHtml() does seem to be correct. Where do I have to link here or what to return. – Simon Franzen Jan 31 '18 at 20:49
  • Oh ok. I was on the wrong track. I still used the old URL in my browser. But what about the getSettingHTML -> I think it is not needed, because defined other routes and templates – Simon Franzen Jan 31 '18 at 20:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.