Ultra Double Secret Manual: Shared Form Part One
But, Arrays Are Illegal!
One of the more understated changes to ExpressionEngine over the last few years is the Shared Form View. Easily, one of my top 3 favorite reasons for why to use ExpressionEngine as a programmer. If you’re not familiar, the nickle explanation is you create form views with array definitions.
I know. Sounds weird. And your instinct to finger wag and wellwhatabout is a natural instinct that’s served you well. Tamp it down for just a minute though; you won’t be disappointed.
Putting aside, “arrays are primitives and you can’t build abstractions around primitives *RAWR*” (except when YOU do it), the implementation ExpressionEngine created allows for some incredibly complex and nuanced solutions that go way beyond what the docs provide. And the docs, as a matter of fact, provide for a lot.
Fun fact; the majority of ExpressionEngine’s Control Panel forms are written using the Shared Form View, so, I mean, examples are all over the place if you’re curious how to do something. Just find it and roll up your sleeves.
The Basics
So, how do you make a form? No matter what anyone tells you (he says in regards to the straw-man just to make a point), there are really only 2 “chunks” required for your Shared Form View; the Control Panel View and the Shared Form array.
Control Panel View
At the most basic, the below is the minimum that’s required for the view within the mcp
method. Same as every other Control Panel View you’ve created; declare some variables and return an array with a body
key (and others, but that’s a discussion for another place).
$variables = [
'cp_page_title' => 'Your Custom Form',
'save_btn_text' => 'save',
'save_btn_text_working' => 'saving',
'base_url' => ee('CP/URL')->make('addons/settings/custom-module')->compile(),
'sections' => $this->getForm() //returns the Shared Form array
];
return [
'body' => ee('View')->make('ee:_shared/form')->render($variables)
];
Note that all the keys within the $variables
array are required for use of the 'ee:_shared/form'
view script (provided by ExpressionEngine). You’ll get PHP errors and undefined variables warnings. It’s ugly. Don’t do it. Show some pride in your work. Declare at least those. If you wanna go bare-bones, this is the way, though there are a ton of other options.
Keep in mind the above
sections
key within the$variables
array; that’s where ALL form arrays are expected within theee:_shared/form
view script. Why it’s not namedforms
is none of our business, to be honest, and it’s rude to ask.
Shared Form Array
To keep things sane, don’t be that developer that just dumps the entire form array into the Controller creating a 1,000 line method within a sea of other 1,000 line methods; separate your code by concern, dammit! I mean, not like I’m about to do. Do better than the below method within the Control Panel object. The below is dumb ‘cause writing examples give me a free pass to be bad at designing my software and double standards are fun.
protected function getForm()
{
return [
[
[
'title' => 'Email',
'fields' => [
'email' => [
'name' => 'email',
'type' => 'text',
],
],
],
[
'title' => 'Name',
'fields' => [
'name' => [
'name' => 'name',
'type' => 'text',
],
],
]
]
];
}
Let’s break this down. It’s obviously an array of arrays that contain arrays (O.o) which define form fields. Pretty straight forward concept but this implementation is deceptive; it’s really more a collection of field groups that can contain field sets that can contain multiple fields. The key (puns are fun!) to this is fields
; it, too, is an array of arrays.
A Different Way
Consider the below:
protected function getForm()
{
return ['My Name Fields' =>
[
[
'title' => 'Contact Details',
'fields' => [
'email' => [
'name' => 'email',
'type' => 'text',
'placeholder' => 'Email',
],
'name' => [
'name' => 'name',
'type' => 'text',
'placeholder' => 'Name',
],
],
]
]
];
}
Same form fields, just presented differently. And because they’re arrays (even though primitives ARE stupid, I know), we can really make our forms as nuanced as… well… how can I put this… our forms can be as nuanced as our clients believe they need their interpretation of a solution to the problem they’re solving… requires…
Note the array key
My Name Fields
allows you to put a header (h-something-or-other) in the HTML to delineate your field group. I’m not going to go into it because the docs cover it nicely but check out using Tabs within your Shared Form Views. It’s pretty snazzy.
Available Control Panel Variables
So, one of the things the docs don’t cover very much is the shear number of variables you can pass to a Shared Form View. Here’s a complete example with every option:
$variables = [
'save_btn_text' => 'save',
'save_btn_text_working' => 'saving',
'ajax_validate' => true,
'has_file_input' => true,
'alerts_name' => '',
'form_hidden' => [],
'cp_page_title_alt' => 'Hello',
'cp_page_title' => 'Will not show',
'action_button' => [],
'hide_top_buttons' => true, //note if 'action_button' is defined this is ignored
'extra_alerts' => [],
'buttons' => [],
'base_url' => ee('CP/URL')->make('addons/settings/custom-module')->compile(),
'sections' => $this->getForm()
];
return [
'body' => ee('View')->make('ee:_shared/form')->render($variables)
];
Variable Definitions
Variable | Definition | Type | Required |
---|---|---|---|
save_btn_text |
Used as the label value within default form buttons | string | Yes |
save_btn_text_working |
Clicked form buttons will have their value changed to this | string | Yes |
base_url |
The URL string to use for form processing | string | Yes |
sections |
The Shared Form View array | array | Yes |
cp_page_title |
Text to display on the View Header | string | Yes |
ajax_validate |
Adds the CSS class ajax-validate to the form tag presumably for reasons |
boolean | No |
has_file_input |
Adds enctype="multipart/form-data" to the form to allow files to be uploaded along with POST |
boolean | No |
alerts_name |
The name for the alerts data specific to your form. Defaults to shared-form |
string | No |
form_hidden |
Any form specific hidden fields you want to attach. Note it MUST be compatible with the form_open() method's parameter |
array | No |
cp_page_title_alt |
An alternative Text to display on the View Header. Useful for multi form views (I imagine) | string | No |
extra_alerts |
A simple array containing the shortname for additional Alerts you want this form to output. See the Cp/Alert Service for details. | array | No |
hide_top_buttons |
Whether to remove the top most submit button from your form. Note if an action_button is defined this setting is ignored. |
boolean | No |
action_button |
An array containing a complete replacement for the top most button (see below) | array | No |
buttons |
Complete override of the buttons on the bottom of the form (see below) | array | No |
Most of the above are pretty self explanatory, but the buttons
and action_button
also have some nuance.
action_button
The format for this array should look like this:
[
'rel' => '',
'href' => '',
'text' => '',
]
buttons
This is a multidimensional array that contains definitions for multiple buttons:
'buttons' => [
[
'shortcut' => '',
'attrs' => '',
'value' => '',
'text' => '',
'name' => '',
'type' => '', //submit|button|reset (yeah, reset, 'cause 1998 happened once and it can happen again)
'class' => '',
'html' => '',//prepends to 'text' value
'working' => '',
]
]
Field Set Definitions
So, we’ve already gone into the basics on how a Shared Form View form is created, but just like with the Control Panel there are quite a few hidden gems available to developers. Unfortunately, it’s broken up into 2 separate layers, with the second layer being conditional.
Consider this form array containing 2 fields:
$form = ['member_details' =>
[
[
'title' => 'Email',
'fields' => [
'email' => [
'name' => 'email',
'type' => 'text',
],
],
],
[
'title' => 'Name',
'fields' => [
'name' => [
'name' => 'name',
'type' => 'text',
],
],
]
]
];
Looking at the commonalities, it’s easier for me to consider this 2 parts that make a whole; the fields
key and everything BUT the fields
key (we’ll call that “Top”).
Top Keys
Here’s a breakdown of the accepted keys:
Variable | Definition | Type | Required |
---|---|---|---|
title |
The colloquial name for the field (processed through the lang() method) |
string | Yes |
fields |
An array of key => $fields that define the actual input layer |
array | Yes |
desc |
A longer description for the field (processed through the lang() method) |
string | No |
desc_cont |
A second description to use for the field that'll be displayed on its own line (processed through the lang() method) |
string | No |
example |
A simple string output (processed through the lang() method) |
string | No |
button |
An array that defines a button; will attach button next to field(s) | array | No |
So a more full fledged example of our form could look like this:
$form = ['member_details' =>
[
[
'title' => 'Email',
'desc' => 'Put Email here',
'desc_cont' => 'My did I capitalize Email above?',
'example' => 'WHY DID I DO IT AGAIN THOUGH?!?',
'fields' => [
'email' => [
'name' => 'email',
'type' => 'text',
],
],
'button' => [ //only one per field (apparently)
'text' => 'Clickety clackity click',
'rel' => '',
'for' => '',//adds to the data-for attribute
]
],
[
'title' => 'Name',
'fields' => [
'name' => [
'name' => 'name',
'type' => 'text',
],
],
]
]
];
Next Steps
Believe it or not, all the above just barely scratches the surface when it comes to the Shared Form View layer of ExpressionEngine. We’ve covered everything up to defining individual fields. Which is a lot. But I’m not going to go into the rest of it for now since dealing with Fields is well documented and they really do provide a good jumping off point at the official docs. For now, we’re done. Go play. Copy/paste the above into a project and tilt your head at how easy it is to create Control Panel forms with ExpressionEngine.
Comments 0
Be the first to comment!