Проблема в том, что ConfigureProductType использует * _SET_DATA
Позвольте мне поделиться этим кодом с
<?php
class ConfigureProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$product = $options['product'];
$orderItem = $options['data'];
// Type.
$builder->add('type', ChoiceType::class, array(
'label' => 'configure_product.type.label',
'choices' => ProductHelper::getOrderTypes($product),
'choice_label' => function($choice, $key, $value) {
return sprintf('configure_product.type.choices.%s', $choice);
},
'constraints' => array(
new NotBlank(array('message' => 'configure_product.type.not_blank')),
),
'attr' => array(
'class' => 'configure-product-type'
),
'empty_data' => $orderItem->getType() ?? ProductHelper::TYPE_ORDER_DEFAULT,
'expanded' => true,
));
$builder->addEventListener(FormEvents::POST_SET_DATA, function(FormEvent $event) use ($options) {
if (null === $item = $event->getData()) {
return;
}
$form = $event->getForm();
$form->add('length', IntegerType::class, array(
'label' => 'configure_product.length',
'attr' => array(
'min' => static::LENGTH_MIN,
),
'empty_data' => '100',
));
$form->add('width', IntegerType::class, array(
'label' => 'configure_product.width',
'attr' => array(
'min' => static::WIDTH_MIN,
'step' => static::WIDTH_STEP,
),
'empty_data' => '100',
));
});
}
/**
* {@inheritDoc}
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(array(
'data_class' => OrderItem::class,
'translation_domain' => 'forms',
'product' => null,
));
}
}
Как вы могли заметить, для ConfigureProduct Type нужны продукт и данные опции элемента заказа, а также * _SET_DATE , Позвольте мне объяснить это еще немного. ConfigureProductType - это форма, используемая в веб-интерфейсе приложения для настройки продукта. На данный момент данные продукта известны в форме.
В бэкэнде мы хотим использовать ту же форму ConfigureProductType, но теперь вам нужно сначала выбрать продукт, затем запрос ajax отправляет форму, чтобы форма знала продукт, но затем, как мы можем использовать повторно ConfigureProductType. Попытка вызвать parent :: buildform в приемнике событий, но он не работает, см. Пример ниже (второй подход с расширением ConfigureProductType)
<?php
class OrderItemType extends ConfigureProductType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('amount', IntegerType::class, array(
'label' => 'order.amount',
'attr' => array(
'min' => 0,
),
'data' => 1,
'required' => false,
));
$builder->add('configureProductType', ConfigureProductType::class, array(
'label' => false,
'show_submit_btn' => false,
'required' => false,
));
$orderItemModifier = function(FormInterface $form, OrderItem $orderItem, $eventType = null) use ($builder, $options) {
if(null === $product = $orderItem->getProduct()) {
return;
}
// how to rebuild options with selected product and then call parent
// parent::buildForm($builder, $options); ??
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) use ($orderItemModifier) {
$form = $event->getForm();
if(null === $orderItem = $event->getData()) {
return;
}
$orderItemModifier($form, $orderItem, FormEvents::PRE_SET_DATA);
});
$builder->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) use ($orderItemModifier) {
$form = $event->getForm();
if(null === $orderItem = $event->getData()) {
return;
}
$orderItemModifier($form, $orderItem, FormEvents::SUBMIT);
});
}
/**
* {@inheritDoc}
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults(array(
'data_class' => OrderItem::class,
'translation_domain' => 'forms',
'allow_extra_fields' => true
));
}
}