简体   繁体   中英

Symfony2.3 Dynamic form fields from two entitnes

I am trying to create a Product form that has multiple attributes from AttributeSet. The attributes are assigned to the AttributeSet and when the product form is loaded all the assigned attributes will be rendered in the form, Each attribute has a type (text, choice, radio etc...)

I am not sure if this is the right way (I am sure there is a cleaner/better way to do so), but I did it like this:

First added EventSubscriber to the main Product form type

$builder->addEventSubscriber($this->buildProductAttributeFormListener)

In the EventSubscriber I have preSetData event:

public function preSetData(FormEvent $event)
{
    $product = $event->getData();
    $form = $event->getForm();

    if (null === $product->getAttributeSetId()) {
        // need to get attribute set id from request
        $request = Request::createFromGlobals()->get('rs_product_type_step');
        $attributeSetId = $request['attribute_set_id'];
        if (!$attributeSetId) {
            $request = Request::createFromGlobals()->get('rs_product');
            $attributeSetId = $request['attribute_set_id'];
        }
        // get assigned attribute set
        $attributeSet = $this->asRepository->find($attributeSetId);
    } else {
        $attributeSet = $product->getAttributeSetId();
    }

    // If product has attributes, lets add this configuration field.
    if ($attributeSet->hasAttributes()) {
        $form->add('attributes', 'rs_product_attribute_collection', array(
            'options'  => $attributeSet->getAttributes(),
            'required' => false
        ));
    }
}

Inside the 'rs_product_attribute_collection' type, I have this buildForm:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // this loop adds each attribute as a field with his type (choice, text, etc...)   
    foreach ($options['options'] as $i => $attribute) {
        if (!$attribute instanceof AttributeInterface) {
            throw new LogicException('Each object passed as attribute must implement "AttributeInterface"');
        }

        $fieldOptions = array(
            'label' => $attribute->getName(),
        );

        if ($attribute->getType() == 'choice') {
            // add custom options for choice type
            //$fieldOptions = array_merge($fieldOptions, array('mapped' => false));
        }

        if (is_array($attribute->getOptions())) {
            $fieldOptions = array_merge($fieldOptions, $attribute->getOptions());
        }

        $builder->add($attribute->getId(), $attribute->getType(), $fieldOptions);
    }
}

Now I have few issues with these... 1) I am not sure if this is the right way to do so because the form->bind isn't bind the data correctly, so I added PRE_SUBMIT event to get the attributes data from the request and manually assign the attributes to Product. 2) The validation is throwing "This value is not valid" error message for 'choice' field type.

I would like to hear ideas how to make it work.

Thanks, Ron.

You would need to make the data_class dynamic as well, so that it will use the attributes set fields you adding.

Also, check this for more details on How to Dynamically Modify Forms Using Form Events http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM