Notes on Updating Plugins for Craft 2.5
Craft 2.5 gives us several new opportunities in our Craft CMS plugins. Pixel & Tonic has provided a helpful overview of new features that we can now include in our plugins: Updating Plugins for Craft 2.5 .
This article is a collection of some of my notes as our team upgraded a few plugins to 2.5 and take advantage of the new features and UI updates. If you choose to take advantage of some of the new Craft 2.5 UI features like sub-navigation and full page forms, your plugin will need to require Craft 2.5 or higher to work properly.
Sub-Navigation
In Craft 2.5, the Control Panel navigation is removed from the top of the browser page and moves to the right sidebar. It also adds support for sub-navigation which gives us the opportunity to move any top level tab navigation in our plugins to the sidebar.
To add sidebar navigation to your plugin, you can set the subnav
variable in any template that extends Craft’s _layouts/cp
or _layouts/elementindex
templates.
{% set subnav = {
entries: {
label: "Entries"|t,
url: url('sproutforms/entries')
},
forms: {
label: "Forms"|t,
url: url('sproutforms/forms')
}
} %}
If some parts of your nav are only accessible for users with certain permissions, they can be merged in to your subnav
on a conditional basis.
{% if currentUser.can('editSproutFormsSettings') %}
{% set subnav = subnav|merge({
settings: {
label: "Settings"|t,
url: url('sproutforms/settings')
}
}) %}
{% endif %}
The top-level keys in your subnav hash are the values that you will need to display the selected state. In this example, those values can be entries
, forms
, or settings
, and each section has a direct relationship with the second segment in the URL of our control panel section. This allows us to add support for our selected states by setting selectedSubnavItem
to the second segment of the URL:
{% set selectedSubnavItem = craft.request.segment(2) %}
Moving the top-level tab navigation to the sidebar as sub-navigation also helped us simplify breadcrumbs in our plugins to be more specific to the sections they relate to.
If you update your top level navigation from tabs to sub-navigation, all users of your plugin prior to 2.5 will not see any top level navigation in your plugin.
Full Page Forms
One significant UI and template update in Craft 2.5 is how Save Buttons are handled. Throughout the Control Panel, we no longer see Save Buttons appear at the end of forms, we see them appear at the top right hand side of each form. While, this is a little unintuitive at first from the user perspective, and I’m sure there can be a healthy debate of the usability of such placement, in updating several plugins it was noticeable how much more consistent the placement of the buttons are in this location.
To adopt this convention in your plugins, you’ll need to update your forms to use the new fullPageForm
variable and saveButton
block:
{% set fullPageForm = true %}
{% block saveButton %}
<div class="buttons">
<input type="submit" class="btn submit" value="{{ 'Save'|t }}">
</div>
{% endblock %}
Setting fullPageForm
to true will wrap your entire Control Panel layout area in a Form tag, giving you the flexibility to place the save button higher on the page. In doing so, Craft also handles CSRF protection for you, so you can also remove your previous <form>
and {{ getCsrfProtection() }}
tags.
Where previously, you needed to build your entire form:
{% set content %}
<form method="post" accept-charset="UTF-8">
{{ getCsrfProtection() }}
<input type="hidden" name="action" value="sproutForms/forms/saveForm">
... FORM FIELDS ...
<div class="buttons">
<input type="submit" class="btn submit" value="{{ 'Save'|t }}">
</div>
</form>
{% endset %}
Your template code would now be updated to something like this:
{% set fullPageForm = true %}
{% block saveButton %}
<div class="buttons">
<input type="submit" class="btn submit" value="{{ 'Save'|t }}">
</div>
{% endblock %}
{% set content %}
... FORM FIELDS ...
{% endset %}
On index pages where you may not have a full page form, you can override the extraPageHeaderHtml
variable to place a button in the same location as saveButton
block:
{% set extraPageHeaderHtml %}
<div class="buttons">
<a class="btn submit add icon" href="{{ url('sproutforms/forms/new') }}">{{ "New Form"|t }}</a>
</div>
{% endset %}
Depending on how you were previously using your form tag, make sure you also update any CSS or JS references that may have relied on a custom form id or class that you had on your form tag that Craft may treat differently on its fullPageForm
form tag. You can no longer set custom values on the form element so any CSS or JS that relied on your form tag may need to be handled in another way for now.
Additionally, full page forms can also handle your shortcut redirect behavior for you. The saveShortcutRedirect
variable can be used to set the data-save-redirect
value on your form tag.
{% set fullPageForm = true %}
{% set saveShortcutRedirect = 'sproutforms/forms/edit/{id}' %}
Sidebar Meta Panes
Sidebars Meta has also received some nice updates in Craft 2.5. Previously, the sidebar input fields behaved much like any other form in Craft – stacking labels on top of input fields. If you don’t change anything about your sidebars, they will continue to look this way and work fine.
Classic sidebar panes:
<div class="pane”> ... </div>
Meta sidebar panes:
<div class="pane meta”> ... </div>
But you also have a new option now, which is worth consideration. By adding an additional meta
class to a pane in your sidebar, Craft will collapse the padding within that pane and update fields to place the label and input of a field on a single line. This helps reinforce the relationship between related fields and reduce the amount of vertical space between fields and panes in the sidebar. We found that this update helped simplify and tighten the sidebar UI for multiple plugins.
Icons, Descriptions, Documentation, Schema Version, Release Notes
In addition to UI updates, Craft 2.5 ships with several items that I will call eco-system updates. They are changes that affect the UI, but more importantly, they allow our plugins connect their lives outside of Craft with their lives in Craft.
Craft’s Plugin Settings page now allows you to display a plugin-specific icon, description, and link to documentation.
An icon can be added to display on the plugin page and in the sidebar area by placing two icon svg files in your resources folder:
/pluginname/resources/icon.svg
/pluginname/resources/icon-mask.svg
You can add support for your plugins Description, Documentation URL, Schema Version, and Release Notes by adding the respective methods to your plugin’s primary class file:
public function getDescription()
{
return 'Simple, beautiful forms. 100% control.';
}
public function getDocumentationUrl()
{
return 'http://sprout.barrelstrengthdesign.com/craft-plugins/forms/docs';
}
public function getSchemaVersion()
{
return '2.1.1';
}
public function getReleaseFeedUrl()
{
return 'https://sprout.barrelstrengthdesign.com/craft-plugins/forms/releases.json';
}
Allowing plugins to define a schemaVersion
provides a nice usability improvement where Craft no longer needs to go into “update mode” if a plugin doesn’t require any database updates.
If a plugin provides a Release Feed, Craft will check for any updates you released when it checks for it’s own updates. This makes it easier for us to communicate to users that new versions of software exist and standardizes how we can communicate about the details of those updates, including critical updates.
Depending on how you manage your plugin release notes, you may need to do a little extra work to get them into the proper JSON format. If you store them in something like a Matrix field, you can likely just output them in the correct format. If you use Markdown or another way, you might need to take an extra step to parse reference tags (if you use them) or clean up spacing before outputting your notes as text for the JSON feed.