In my current project I'm using nested Zend\Form\Fieldset
s and Zend\Form\Collection
s, that provide an extremely comfortable way to map complex object structures to the form, in order to get a complete object (ready to be saved) from the form input.
To the problem: I have a Fieldset
FooFieldset
containing an Element
foo_element
with a Label
"foo element" (code see below) and need to use this twice: 1. as a single Fieldset
; 2. in a Collection
. At the first place in the form I want its elements to be displayed; at the the second place I want to disable the labels (or maybe change them). (I also want to format it another way in the second case, but the most important thing now is the label.)
How to decorate Zend\Form\Element
s of a Zend\Form\Fieldset
in a Zend\Form\Element\Collection
depending on the context?
Code
class FooFieldset extends Fieldset implements InputFilterProviderInterface
{
public function init()
{
$this->add([
'type' => 'text',
'name' => foo_element',
'options' => ['label' => _('foo element')]
]);
}
public function getInputFilterSpecification() { ... }
}
class BarFieldset extends Fieldset implements InputFilterProviderInterface
{
public function init()
{
$this->add([
'name' => 'foo',
'type' => 'My\Form\Fieldset\Foo',
'options' => []
]);
}
public function getInputFilterSpecification() { ... }
}
class BuzFieldset extends Fieldset implements InputFilterProviderInterface
{
$this->add(
[
'name' => 'foos',
'type' => 'Zend\Form\Element\Collection',
'options' => [
'label' => _('multiple foos'),
'count' => 5,
'should_create_template' => true,
'template_placeholder' => '__placeholder__',
'allow_add' => true,
'target_element' => [
'type' => 'Order\Form\Fieldset\Foo',
],
'label_attributes' => [
'class' => 'col-md-12'
]
]
]);
public function getInputFilterSpecification() { ... }
}
echo $this->formRow($myForm->get('main_fieldset')->get('bar')->get('foo')->get('foo_element');
echo $this->formRow($myForm->get('main_fieldset')->get('buz')->get('foos');
Workaround 1
It would be possible to use another Fieldset
, e.g. a sub-class of FooFieldst
(sometnig like FooFieldsetForUsingInCollection extends FooFieldst
) and adjust the Label
(and other settings) there.
Workaround 2
It also would be possible to access the Collection
's Element
s in the view script and manipulate them there (as here demonstrated). But I don't really like this solution, since then the Fieldset
is defined at multiple places. And it also need further effort, if the number of the Collection
elements is variable.
It seems like you need to reuse the 'foos' collection and the 'bar' element together in their own fieldset while keeping how it is currently created.
I would
Move the collection element
foo
out of theBuzFieldset::init
and into it's own factory (create the element and all it's options in the factory).Register it with the form element manager as and new service, lets call it
FooCollection
. This element is now reusable and can be called from the form element manager as$fem->get('FooCollection')
.Replace removed
$fieldset->add('type' => 'Zend\Form\Element\Collection')
with$fieldset->add('type' => 'FooCollection')
inBuzFieldset
.Repeat for
foo_element
with a new service name ofFooElement
.Then you need to create a new fieldset factory called
FooCollectionAndFooElementFieldsetFactory
this factory will return a new fieldset with both theFooCollection
andFooElement
attached.In the factory of
main_fieldset
decide if you need to attachFooCollectionAndFooElementFieldsetFactory
or the existingbar
orbaz
fieldsets.