It's a common problem! Forms can really be a slow-down with ZF2.
I use Twig (recommended) but you can port this approach to plain old ZF2 templates too.
Here's one such template I use nearly everywhere:
horizontal_form.twig
{# render rows only, not the form tag #}
{% do form.prepare() %}
{% for f in form %}
{% do f.setOption( 'twb-layout', 'horizontal' ) %}
{{ formRow( f ) }}
{% endfor %}
I've got a second with a slightly different approach to support a specific IdentifiableForm in my code:
identifiable_form.twig
<form id="{{ form.getAttribute('name') }}" name="{{ form.getAttribute('name') }}" action="{{ form.getAttribute('action') }}" class="form-horizontal" role="form">
<input type="hidden" name="class" value="{{ form.getAttribute('class') }}">
{% for f in form %}
{% do f.setOption( 'twb-layout', 'horizontal' ) %}
{% do f.setOption( 'twb-form-group-size', 'form-group-sm' ) %}
{{ formRow( f ) }}
{% endfor %}
<div class="hr-line-dashed"></div>
<button type="submit" class="btn btn-primary ladda-button" data-style="expand-right">Save</button>
</form>
With those two in the pocket, my usage looks like this:
In a twig template that should use a form
...include the template from the other:
<div class="panel-body">
{% set form = general_config_form %}
{% do form.prepare() %}
{% include 'application/generic/identifiable_form' %}
</div>
The controller action that operates that template looks like:
$vm = new ViewModel();
$vm->setTerminal( true );
$vm->setTemplate( 'application/admin/config/index' );
$sm = $this->getServiceLocator();
$fm = $sm->get( 'FormElementManager' );
$country = $config_mapper->get('general.country', true );
$general_config_form = $fm->get( GeneralConfigForm::class, [ 'country' => $country ] );
$general_config_form->setAttribute('action', '/admin-config/form-save' );
$vm->setVariable( 'general_config_form', $general_config_form );
In the end it's just a game of:
- instantiating/loading the form in the action
- setting the form as a variable in the ViewModel
- including the "generic form template" from that action's actual template
On topic, if you hate rigging forms as much as I do, I made a little tool to save time here: https://github.com/Saeven/zf2-circlical-formtool
Second, if you use Bootstrap in your app, this form helper replacement really makes things look nice: https://github.com/neilime/zf2-twb-bundle
Good luck!