Creating a Form Block Custom Template
In concrete5 5.7 and earlier, customizing the output of the form block was a bit cumbersome – but it was possible. This was done by creating a custom template for the form block and editing the markup from within that. The output of the form block has improved over time, and 5.7 found the block with reasonable block view templates for editing the success message, validation error messages and field group HTML.
Unfortunately, all the markup for the actual form elements themselves was contained within the Form block controller, meaning that in order to fully customize form elements you needed to fork the view template and the controller. Furthermore, the logic for the elements was fairly rigid and resulted involved working with spaghetti code. Maintainability was a challenge.
In version 8, the form block was changed to be powered by Express Forms – and in the short term this actually made things worse. From a flexibility standpoint it was much, much improved – you could add new attribute types to the system and they would be available to use in front-end forms, for example. But in terms of customizing markup, consider the following form:
This is an Express form with some attributes and an association control (the Binder form control, which is a one-to-many association with the Binder object). It looks great in the default Elemental theme, because the Elemental theme uses Twitter Bootstrap for form rendering, and the attributes in the core do as well. That means that the attributes will look good in the Dashboard form context, and the front-end form context.
However, what about sites that don't use Twitter Bootstrap. Consider the form in a different concrete5 theme, one that uses a completely custom scheme for form markup?
Doesn't look so good, does it? While we do advocate for standardization, and build our themes to conform to Twitter Bootstrap, we definitely don't mandate a particular CSS skeleton for theming, and concrete5 has always been built for agencies for theming flexibility. So this is a problem.
Forking Attribute Views?
Unfortunately, we can't just create a custom template to fix this. Our logic isn't found within the Form block any longer – it's spread across all attribute types in concrete5. Yes, we could fork the core attribute views by creating
application/attributes/text/form.php in our application directory, and make changes there – but these changes are made globally. That means that they'll be used when showing forms in the Dashboard – and the dashboard needs the attributes to use bootstrap styling (for best display.) We have a problem. We need to use one set of attribute view templates for displaying controls on the front-end of the site, and a different set for showing them in the Dashboard.
Enter Contexts. Using contexts, you can specify where you're rendering a form, and the context object itself can tell concrete5 where to try to load templates from. This works at the attribute level and at the form level, making it so that you can customize the entire form of an express object wherever it's embedded in your site, without worrying about attributes breaking when displayed in the Dashboard, the attributes panel, or elsewhere.
Let's dive into Express Form theming. First, lets take a look at what is possible by simply using a Form custom template. As described above, not everything is possible, so we'll start there and then move into using contexts for form control customization. Read on for more information.