1

I'm trying to understand and get around this whole form collection thing, but the documentation isn't really expansive and I just can't find out how to do some specific things I need.

I will refer to the example in the official manual to explain what i need:

  1. When the collection is created, you get to use a custom fieldset as target:

    $this->add(array( 'type' => 'Zend\Form\Element\Collection', 'name' => 'categories', 'options' => array( 'label' => 'Please choose categories for this product', 'count' => 2, 'should_create_template' => true, 'template_placeholder' => '__placeholder_:', **'target_element' => array( 'type' => 'Application\Form\CategoryFieldset', )**, ), ));

However, I need to pass an argument to the specific fieldset's constructor, in my case a translator instance in order to be able to translate within the fieldset.

class CategoryFieldset extends Fieldset { public function __construct($translator) }

  1. Fieldset's label: as you can see in the example, the collection outputs all the copies of the fieldset with the same specified label "Category". I would need, instead, to have that label numbered, to show "Category 1", "Category 2" etc. based on the collection's count. Is this even possible? Form collection example

Thanks for your help!

Dennis
  • 7,907
  • 11
  • 65
  • 115
Aise
  • 173
  • 2
  • 13
  • Did you solve this. I've implemented the functionality you are trying to achieve many times. But it's a pain and I don't want to explain if you worked it out, since you asked 2 days ago ... – Purple Hexagon Feb 01 '16 at 22:53
  • I kinda figured out the category label part, not sure if it's the correct approach but it works: I just put a placeholder in the labels too, so they get numbered by JS together with the indexes. About the translator, I still didn't solve it; I found many solutions to get the Service Manager from within the fieldset, but none of them work when I generate the fieldset as a target type of a collection. – Aise Feb 02 '16 at 08:29
  • @PurpleHexagon can you still help about the translator, please? – Aise Feb 04 '16 at 14:09
  • I can, is it possible to post more complete code for the form? And the specific issue with the translator? – Purple Hexagon Feb 05 '16 at 07:49
  • So, this is the relevant part of the form: `class Contact extends Form { public function __construct($translator) { $this->add(array( 'name' => 'people', 'type' => 'collection', 'options' => array( 'label' => $translator->translate("People"), 'target_element' => array('type' => 'Application\Form\PersonFieldset'), 'count' => 2, ), )); } }` And this is the PersonFieldset: `class PersonFieldset extends Fieldset { public function __construct($translator) { _My fields here; I need to access the translator but I can't pass it from the collection element._ } }` – Aise Feb 05 '16 at 10:19
  • I will never understand how to properly format the comments here... -_- – Aise Feb 05 '16 at 10:25
  • Are you getting the form out of the FormElementManager? I think it should inject the translator for you if you are? – Purple Hexagon Feb 05 '16 at 17:06
  • I don't know if it's injecting the translator, but if I just use `$translator->translate("...");` in the fieldset like I do in the form, it doesn't work as $translator isn't defined. If it is injected by FormElementManager, how am I supposed to access it? – Aise Feb 05 '16 at 23:40
  • Sorry I didn't really get what you mean by getting the form out of FormElementManager; I'm just creating a new form from the controller, passing it the translator as an argument; I would do the same with the fieldset, but since the collection element is calling it, I don't know how to do. I tried several methods found on other topics to retrieve the translator from the service locator within the fieldset, but I can't access the application-wise service manager. – Aise Feb 06 '16 at 08:02
  • I just figured out I could just pass the translator to the collection fieldset like this: `'target_element' => new \Application\Form\PersonFieldset($translator)`, so easy but so hard to find out due to the poor documentation.. :/ – Aise Feb 09 '16 at 09:03

2 Answers2

2

I checked source of the Collection. The Collection just clones target_element. My solution is simple and works:

class CategoryFieldset extends Fieldset implements InputFilterProviderInterface
{
    static $lp = 1;// <-----------  add this line

    public function __clone() //<------------ add this method
    {
        parent::__clone(); 
        $oldLabel = $this->elements['name']->getLabel();
        $this->elements['name']->setLabel($oldLabel . ' ' . self::$lp++);
    }
0kph
  • 21
  • 2
0

For the first, do not pass translator to the Fieldset, but use translator outside of the Fieldset. Get the values first, from the form, translate them, then set them back into the form. The bonus is that you keep your form and your translator logic separate.

For the second, use $form->prepare() and then iterate over the Collection.

$form->prepare(); //clones collection elements

$collection = $form->get('YOUR_COLLECTION_ELEMENT_NAME');
foreach ($collection as $fieldset)
    $fieldset->get('INDIVIDUAL_ELEMENT_NAME')->setLabel("WHATEVER YOU WANT");

Example:

/*
 * In your model or controller:
 */
$form->prepare();

$collection = $form->get('categories');
foreach ($collection as $fieldset)
{
    $label = $fieldset->get('name')->getLabel();
    $translatedLabel = $translator->translate($label);
    $fieldset->get('name')->setLabel($translatedLabel);
}
Dennis
  • 7,907
  • 11
  • 65
  • 115