# formCollection with templated elements?

**URL:** <https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977>\
**Category:** Components & MVC\
**Tags:** laminas-form\
**Created:** [December 1, 2020, 11:54am UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977 "2020-12-01T11:54:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![MatteoF](https://avatars.discourse-cdn.com/v4/letter/m/65b543/32.png) [@MatteoF](https://discourse.laminas.dev/u/MatteoF)\
**Post date:** [December 1, 2020, 11:54am UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/1 "2020-12-01T11:54:12Z")

</div>

Im trying to figure out how do i implement this scenario:  
I’ve got a form and i need to display a collection and user can dinamically add elements to that collection, formCollection with shouldCreateTemplate seems perfect for the job until i need to assign a custom style template to those elements.

Im looking how to use View Helpers but im stuck, any hints/solutions?

_I also tried to partialLoop the collection to a template.phtml, i can perfectly render them but i lose the “shouldCreateTemplate” function_

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [December 1, 2020, 12:21pm UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/2 "2020-12-01T12:21:47Z")

</div>

Hello and welcome to our forums! 😃

> [@MatteoF](#):
>
> i need to assign a custom style template to those elements.

There are many options. The view helper `formCollection` adds a `fieldset`, a `legend` and the `template` but everything else is rendered by the `formRow` helper – if nothing else has been set.

Can you give an example which part should get a custom style?

---

<div class="post-metadata">

**Author:** ![MatteoF](https://avatars.discourse-cdn.com/v4/letter/m/65b543/32.png) [@MatteoF](https://discourse.laminas.dev/u/MatteoF)\
**Post date:** [December 1, 2020, 2:00pm UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/3 "2020-12-01T14:00:22Z")

</div>

here some code:

> **Form Class**
>
> ```
> <?php 
> namespace Form\Model\Entity;
> 
> use Laminas\Form\Annotation; //annotation is for fun
> 
> /**
> * @Annotation\Name("form")
> */
> class Form {
> 
> //[...]
>     
> /**
> * @Annotation\Name("child")
> * @Annotation\Type("Form\Model\Entity\Privato\Coll")
> */
> private $child_coll;
> }
> ?>
> 
> ```

> **Collection Class**
>
> ```
> <?php
> namespace Form\Model\Entity\Privato;
> 
> use Laminas\Form\Element;
> 
> class Coll extends \Laminas\Form\Fieldset implements \Laminas\InputFilter\InputFilterProviderInterface{
> 
> public function __construct() {
> parent::__construct();
> 		
> $this->add([
> 'type' => Element\Collection::class,
> 'options' => [
> 'count' => 1, //test_c
> 'allow_add' => true,
> 'should_create_template' => true,
> 'template_placeholder' => ' __placeholder__',
> 'target_element' => [
> 'type' => CollElemFieldset::class,
> ],
> ],
> ]);
> }
> 
> public function getInputFilterSpecification(): array {
> return [];
> }
> 
> }
> 
> ```

> **Collection Element Class**
>
> ```
> <?php
> 
> namespace Form\Model\Entity\Privato;
> 
> use Laminas\Form\Element;
> 
> class CollElemFieldset extends \Laminas\Form\Fieldset implements \Laminas\InputFilter\InputFilterProviderInterface {
>     
> public function __construct() {
> parent::__construct('child_elem');
>         
> $this->add([
> 'name' => 'surname',
> 'type' => Element\Text::class,
> 'options' => [
> 'label' => 'Cognome',
> ],
> 'attributes' => [
> 'required' => 'required',
> ],
> ]);
> $this->add([
> 'name' => 'name',
> 'type' => Element\Text::class,
> 'options' => [
> 'label' => 'Nome',
> ],
> 'attributes' => [
> 'required' => 'required',
> ],
> ]);
>         
> $this->add([
> 'name' => 'gender',
> 'type' => \Form\Element\GenderSelect::class,
> 'options' => [
> 'label' => 'Sesso',
> ],
> 'attributes' => [
> 'required' => 'required',
> ],
> ]);
>         
> $this->add([
> 'name' => 'maritial_status',
> 'type' => \Form\Element\MaritialStatus::class,
> 'options' => [
> 'label' => 'Stato civile',
> ],
> 'attributes' => [
> 'required' => 'required',
> ],
> ]);
>         
> $this->add([
> 'name' => 'birthday',
> 'type' => Element\Date::class,
> 'options' => [
> 'label' => 'Data di nascita',
> ],
> 'attributes' => [
> 'required' => 'required',
> ],
> ]);
> 
> $this->add([
> 'name' => 'npwp',
> 'type' => Element\Text::class,
> 'options' => [
> 'label' => 'Codice fiscale',
> ],
> ]);
> }
>     
> public function getInputFilterSpecification(): array {
> return [];
> }
> }
> 
> ```

> **child\_elem.phtml**
>
> ```
> <?php
> $reg = $this->reg;
> $formLabel = $this->plugin('formLabel');
> 
> $surname = $reg->get('surname');
> $surname->setAttribute('class', 'form-control custom_surname');
> 
> $name = $reg->get('name');
> $name->setAttribute('class', 'form-control');
> 
> $gender = $reg->get('gender');
> $gender->setAttribute('class', 'form-control');
> 
> $maritial_status = $reg->get('maritial_status');
> $maritial_status->setAttribute('class', 'form-control');
> 
> $birthday = $reg->get('birthday');
> $birthday->setAttribute('class', 'form-control');
> 
> $npwp = $reg->get('npwp');
> $npwp->setAttribute('class', 'form-control npwp');
> ?>
> 
> <div class="box_person">
> <div class="form-row">
> <div class="col-md-5">
> <?php
> echo $formLabel->openTag() . $surname->getOption('label');
> echo $formLabel->closeTag();
> echo $this->formInput($surname);
> echo $this->formElementErrors($surname);
> ?>
> </div>
> <div class="col-md-4">
> <?php
> echo $formLabel->openTag() . $name->getOption('label');
> echo $formLabel->closeTag();
> echo $this->formInput($name);
> echo $this->formElementErrors($name);
> ?>
> </div>
> <div class="col-md-3">
> <?php
> echo $formLabel->openTag() . $gender->getOption('label');
> echo $formLabel->closeTag();
> echo $this->formSelect($gender);
> echo $this->formElementErrors($gender);
> ?>
> </div>
> </div>
> 
> <div class="form-row">
> 		
> <div class="col-md-4">
> <?php
> echo $formLabel->openTag() . $maritial_status->getOption('label');
> echo $formLabel->closeTag();
> echo $this->formSelect($maritial_status);
> echo $this->formElementErrors($maritial_status);
> ?>
> </div>
> <div class="col-md-4">
> <?php
> echo $formLabel->openTag() . $birthday->getOption('label');
> echo $formLabel->closeTag();
> echo $this->formInput($birthday);
> echo $this->formElementErrors($birthday);
> ?>
> </div>
> <div class="col-md-4">
> <?php
> echo $formLabel->openTag() . $npwp->getOption('label');
> echo $formLabel->closeTag();
> echo $this->formInput($npwp);
> echo $this->formElementErrors($npwp);
> ?>
> </div>
> </div>
> </div>
> 
> ```

> **index.phtml**
>
> ```
> <?php
> //...
> 	
> // custom render but no dynamic template
> $collection = $form->get('child')->get('collection');
> $this->partialLoop()->setObjectKey('reg');
> echo $this->partialLoop('child_elem.phtml', $collection);
> 	
> //not custom render but dynamic template
> echo $this->formCollection($collection);
> 	
> //...
> ?>
> 
> ```

> [@froschdesign](#):
>
> everything else is rendered by the `formRow` helper

Should I create a custom formRow view helper and call the child\_elem.phtml ?

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [December 1, 2020, 2:28pm UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/4 "2020-12-01T14:28:53Z")

</div>

> [@MatteoF](#):
>
> Should I create a custom formRow view helper and call the child\_elem.phtml ?

You can set a partial script on the `formRow` helper for the rendering:

```php
$this->formCollection()->setElementHelper(
    $this->formRow()->setPartial('partial.phtml')
);
echo $this->formCollection($form->get('example_collection'));

```

In the partial script you can use the following variables:

```php
/**
 * @var Laminas\Form\ElementInterface $element
 * @var string|null $label
 * @var array|null $labelAttributes
 * @var string|null $labelPosition
 * @var bool $renderErrors
 *

```

---

<div class="post-metadata">

**Author:** ![MatteoF](https://avatars.discourse-cdn.com/v4/letter/m/65b543/32.png) [@MatteoF](https://discourse.laminas.dev/u/MatteoF)\
**Post date:** [December 2, 2020, 2:38am UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/5 "2020-12-02T02:38:18Z")

</div>

Sorry for late reply,  
im testing your solution and i suppose in that _partial.phtml_ i can modify the style of each single element, but how do i differentiate one from another? i’ll attach the code i tried

> **partial.phtml**
>
> ```
> <?php
> $formLabel = $this->plugin('formLabel');
> $element->setAttributes(['class' => 'form-control']);
> ?>
> 
> <div class="col-md-4">
> <?php
> echo $formLabel->openTag() . $label;
> echo $formLabel->closeTag();
> echo $this->formInput($element);
> ?>
> </div>
> ?>
> 
> ```

> **index.phtml**
>
> ```
> //using your code
> $collection = $form->get('child')->get('collection');
> $this->formCollection()->setElementHelper(
> $this->formRow()->setPartial('partial.phtml')
> );
> echo $this->formCollection($collection);
> 
> ```

In this case my partial.phtml contains a **col-md-4** that needs to be different for almost all elements rendered. _(ex. ‘surname’ needs col-md-5 ; ‘gender’ needs col-md-3 ; etc.)_

If i misunderstood your point let me know  
Thanks for your time

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [December 2, 2020, 7:03am UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/6 "2020-12-02T07:03:41Z")

</div>

> [@MatteoF](#):
>
> In this case my partial.phtml contains a **col-md-4** that needs to be different for almost all elements rendered. _(ex. ‘surname’ needs col-md-5 ; ‘gender’ needs col-md-3 ; etc.)_

You can get the name of each element and output the related column class:

```php
$classAttributes = [
    'surname' => 'col-md-5',
    // …
];

```

Another option is to skip the `formCollection` helper and to use a loop:

```php
<?php
/ **Laminas\Form\Element $element** /
foreach($form->get('example_collection') as $element): ?>

    <div class="<?= $classAttributes[$element->getName()] ?>">
        <?= $this->formRow($element) ?>
    </div>

<?php endforeach ?>

```

The template for new elements can be rendered with:

```php
echo $this->formCollection()->renderTemplate($form->get('example_collection'));

```

---

<div class="post-metadata">

**Author:** ![froschdesign](https://yyz2.discourse-cdn.com/flex032/user_avatar/discourse.laminas.dev/froschdesign/32/38_2.png) [@froschdesign](https://discourse.laminas.dev/u/froschdesign)\
**Post date:** [December 2, 2020, 1:09pm UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/7 "2020-12-02T13:09:21Z")

</div>

@MatteoF  
Have you found a suitable solution?

---

<div class="post-metadata">

**Author:** ![MatteoF](https://avatars.discourse-cdn.com/v4/letter/m/65b543/32.png) [@MatteoF](https://discourse.laminas.dev/u/MatteoF)\
**Post date:** [December 2, 2020, 1:42pm UTC](https://discourse.laminas.dev/t/formcollection-with-templated-elements/1977/8 "2020-12-02T13:42:43Z")

</div>

> [@froschdesign](#):
>
> @MatteoF  
> Have you found a suitable solution?

Yeah, applying this solution and some minor edits i managed to solve my problem.

> [@froschdesign](#):
>
> ```php
> $this->formCollection()->setElementHelper(
> $this->formRow()->setPartial('partial.phtml')
> );
> echo $this->formCollection($form->get('example_collection'));
> 
> ```
> 
> In the partial script you can use the following variables:
> 
> ```php
> /**
> * @var Laminas\Form\ElementInterface $element
> * @var string|null $label
> * @var array|null $labelAttributes
> * @var string|null $labelPosition
> * @var bool $renderErrors
> *
> 
> ```

> [@froschdesign](#):
>
> You can get the name of each element and output the related column class:
> 
> ```php
> $classAttributes = [
> 'surname' => 'col-md-5',
> // …
> ];
> 
> ```

Thank you very much! 😃
