mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Tabs docs for CMS
This commit is contained in:
parent
3214a0a756
commit
ada42103ed
@ -110,7 +110,46 @@ before the form itself is layouted with its sibling panels to avoid incorrect di
|
|||||||
SilverStripe constructs forms and its fields within PHP,
|
SilverStripe constructs forms and its fields within PHP,
|
||||||
mainly through the `[getCMSFields()](api:DataObject->getCMSFields())` method.
|
mainly through the `[getCMSFields()](api:DataObject->getCMSFields())` method.
|
||||||
This in turn means that the CMS loads these forms as HTML via Ajax calls,
|
This in turn means that the CMS loads these forms as HTML via Ajax calls,
|
||||||
e.g. after saving a record (which requires a form refresh), or switching the section in the CMS>
|
e.g. after saving a record (which requires a form refresh), or switching the section in the CMS.
|
||||||
|
|
||||||
|
Depending on where in the DOM hierarchy you want to use a form,
|
||||||
|
custom templates and additional CSS classes might be required for correct operation.
|
||||||
|
For example, the "EditForm" has specific view and logic JavaScript behaviour
|
||||||
|
which can be enabled via adding the "cms-edit-form" class.
|
||||||
|
In order to set the correct layout classes, we also need a custom template.
|
||||||
|
To obey the inheritance chain, we use `$this->getTemplatesWithSuffix('_EditForm')` for
|
||||||
|
selecting the most specific template (so `MyAdmin_EditForm.ss`, if it exists).
|
||||||
|
|
||||||
|
Basic example form in a CMS controller subclass:
|
||||||
|
|
||||||
|
:::php
|
||||||
|
class MyAdmin extends LeftAndMain {
|
||||||
|
function getEditForm() {
|
||||||
|
$form = new Form(
|
||||||
|
$this,
|
||||||
|
'EditForm',
|
||||||
|
new FieldSet(
|
||||||
|
TabSet::create(
|
||||||
|
'Root',
|
||||||
|
Tab::create('Main',
|
||||||
|
TextField::create('MyText')
|
||||||
|
)
|
||||||
|
)->setTemplate('CMSTabset')
|
||||||
|
),
|
||||||
|
new FieldSet(
|
||||||
|
FormAction::create('doSubmit')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// Required for correct CMS layout
|
||||||
|
$form->addExtraClass('cms-edit-form');
|
||||||
|
$form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Note: Usually you don't need to worry about these settings,
|
||||||
|
and will simply call `parent::getEditForm()` to modify an existing,
|
||||||
|
correctly configured form.
|
||||||
|
|
||||||
## JavaScript through jQuery.entwine
|
## JavaScript through jQuery.entwine
|
||||||
|
|
||||||
@ -351,6 +390,103 @@ Note that a similar tree logic is also used for the
|
|||||||
form fields to select one or more entries from those hierarchies
|
form fields to select one or more entries from those hierarchies
|
||||||
(`[api:TreeDropdownField]` and `[api:TreeMultiselectField]`).
|
(`[api:TreeDropdownField]` and `[api:TreeMultiselectField]`).
|
||||||
|
|
||||||
|
## Tabs
|
||||||
|
|
||||||
|
We're using [jQuery UI tabs](http://jqueryui.com/), but in a customized fashion.
|
||||||
|
HTML with tabs can be created either directly through HTML templates in the CMS,
|
||||||
|
or indirectly through a `[api:TabSet]` form field. Since tabsets are useable
|
||||||
|
outside of the CMS as well, the baseline application of tabs happens via
|
||||||
|
a small wrapper around `jQuery.tabs()` stored in `TabSet.js`.
|
||||||
|
|
||||||
|
In the CMS however, tabs need to do more: They memorize their active tab
|
||||||
|
in the user's browser, and lazy load content via ajax once they're activated.
|
||||||
|
|
||||||
|
They also need to work across different "layout containers" (see above),
|
||||||
|
meaning a tab navigation might be in a layout header, while the tab
|
||||||
|
content is occupied by the main content area. jQuery assumes a common
|
||||||
|
parent in the DOM for both the tab navigation and its target DOM elements.
|
||||||
|
In order to achieve this level of flexibility, most tabsets in the CMS
|
||||||
|
use a custom template which leaves rendering the tab navigation to
|
||||||
|
a separate template: `CMSMain.ss`. See the "Forms" section above
|
||||||
|
for an example form.
|
||||||
|
|
||||||
|
Here's how you would apply this template to your own tabsets used in the CMS.
|
||||||
|
Note that you usually only need to apply it to the outermost tabset,
|
||||||
|
since all others should render with their tab navigation inline.
|
||||||
|
|
||||||
|
Form template with custom tab navigation (trimmed down):
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
<form $FormAttributes data-layout-type="border">
|
||||||
|
|
||||||
|
<div class="cms-content-header north">
|
||||||
|
<% if Fields.hasTabset %>
|
||||||
|
<% with Fields.fieldByName('Root') %>
|
||||||
|
<div class="cms-content-header-tabs">
|
||||||
|
<ul>
|
||||||
|
<% loop Tabs %>
|
||||||
|
<li><a href="#$id">$Title</a></li>
|
||||||
|
<% end_loop %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% end_with %>
|
||||||
|
<% end_if %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="cms-content-fields center">
|
||||||
|
<fieldset>
|
||||||
|
<% loop Fields %>$FieldHolder<% end_loop %>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
Tabset template without tab navigation (e.g. `CMSTabset.ss`)
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
<div $AttributesHTML>
|
||||||
|
<% loop Tabs %>
|
||||||
|
<% if Tabs %>
|
||||||
|
$FieldHolder
|
||||||
|
<% else %>
|
||||||
|
<div $AttributesHTML>
|
||||||
|
<% loop Fields %>
|
||||||
|
$FieldHolder
|
||||||
|
<% end_loop %>
|
||||||
|
</div>
|
||||||
|
<% end_if %>
|
||||||
|
<% end_loop %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Lazy loading works based on the `href` attribute of the tab navigation.
|
||||||
|
The base behaviour is applied through adding a class `.cms-tabset` to a container.
|
||||||
|
Assuming that each tab has its own URL which is tracked in the HTML5 history,
|
||||||
|
the current tab display also has to work when loaded directly without Ajax.
|
||||||
|
This is achieved by template conditionals (see "MyActiveCondition").
|
||||||
|
The `.cms-panel-link` class will automatically trigger the ajax loading,
|
||||||
|
and load the HTML content into the main view. Example:
|
||||||
|
|
||||||
|
:::ss
|
||||||
|
<div id="my-tab-id" class="cms-tabset" data-ignore-tab-state="true">
|
||||||
|
<ul>
|
||||||
|
<li class="<% if MyActiveCondition %> ui-tabs-active<% end_if %>">
|
||||||
|
<a href="admin/mytabs/tab1" class="cms-panel-link">
|
||||||
|
Tab1
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="<% if MyActiveCondition %> ui-tabs-active<% end_if %>">
|
||||||
|
<a href="admin/mytabs/tab2" class="cms-panel-link">
|
||||||
|
Tab2
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
The URL endpoints `admin/mytabs/tab1` and `admin/mytabs/tab2`
|
||||||
|
should return HTML fragments suitable for inserting into the content area,
|
||||||
|
through the `PjaxResponseNegotiator` class (see above).
|
||||||
|
|
||||||
|
|
||||||
## Related
|
## Related
|
||||||
|
|
||||||
* [Howto: Extend the CMS Interface](../howto/extend-cms-interface)
|
* [Howto: Extend the CMS Interface](../howto/extend-cms-interface)
|
||||||
|
Loading…
Reference in New Issue
Block a user