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 the ee:_shared/form view script. Why it’s not named forms 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.

Eric Lamb's avatar
Eric Lamb

Builds things. Actively looking for clients.

Comments 0

Be the first to comment!