我想問我如何使用類似于 Symfony 食譜中給出的結構來實作動態級聯子級依賴:dynamic_form_modification_using_form_events但有一個附加欄位,該欄位由基于用戶選擇的選項的資料填充。我設法使它與類似于 sports->position 的依賴項一起作業,但我無法使其與結構 categories->categoryChildren->childCategoryChildren 一起作業,其中 categoryChildren 和 childCategoryChildren 都是動態創建的。當我嘗試為 categoryChildren 創建事件偵聽器時,出現錯誤:
名為“categoryChildren”的孩子不存在。
這是我的表單型別:
/**
* Class AddAdType
* @package App\Ad\AdBundle\Form\Type
*/
class CreateAdType extends AbstractType
{
/**
* @param CategoryRepository $categoryRepository
*/
public function __construct(
CategoryRepository $categoryRepository,
)
{
$this->categoryRepository = $categoryRepository;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('description')
->add('price')
->add('category', EntityType::class, [
'class' => Category::class,
'choices' => $this->categoryRepository->findBy(['parent' => null]),
'choice_label' => 'name',
'required' => true,
'placeholder' => 'Wybierz kategorie',
]);
$this->categoryChildrenListener($builder);
$this->childCategoryChildrenListener($builder);
}
/**
* @param FormBuilderInterface $builder
*/
public function categoryChildrenListener(FormBuilderInterface $builder)
{
$formModifier = function (FormInterface $form, Category $category = null) {
$categoryChildren = null === $category ? [] : $this->categoryRepository->findBy(['parent' => $category]);
$form->add('categoryChildren', EntityType::class, [
'class' => Category::class,
'choice_label' => 'name',
'choices' => $categoryChildren,
'mapped' => false,
'attr' => [
'onChange' => "getNewVal(this);"
]
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
$formModifier($event->getForm(), $data->getCategory());
}
);
$builder->get('category')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$ad = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $ad);
}
);
}
/**
* @param FormBuilderInterface $builder
*/
public function childCategoryChildrenListener(FormBuilderInterface $builder)
{
$formChildCategoryModifier = function (FormInterface $form, Category $categoryChild = null) {
$childCategoryChildren = null === $categoryChild ? [] : $this->categoryRepository->findBy(['parent' => $categoryChild]);
$form->add('childCategoryChildren', EntityType::class, [
'class' => Category::class,
'choice_label' => 'name',
'choices' => $childCategoryChildren,
'mapped' => false
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formChildCategoryModifier) {
$data = $event->getData();
$formChildCategoryModifier($event->getForm(), $data->getCategory());
}
);
$builder->get('categoryChildren')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formChildCategoryModifier) {
$ad = $event->getForm()->getData();
$formChildCategoryModifier($event->getForm()->getParent(), $ad);
}
);
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Ad::class,
'csrf_protection' => false
]);
}
}
這是我的物體:
/**
* Class Ad
* @package App\Ad\AdBundle\Entity\Ad
*
* @ORM\Entity
* @ORM\Table(name="ad")
*/
class Ad
{
//[...]
/**
* @ORM\ManyToOne(targetEntity="App\Ad\CategoryBundle\Entity\Category")
* @ORM\JoinColumn(name="category_id", nullable=false, referencedColumnName="id")
*/
private $category;
private $categoryChildren;
private $childCategoryChildren;
//[...]
/**
* @return Category|null
*/
public function getCategory(): ?Category
{
return $this->category;
}
/**
* @param Category|null $category
* @return $this
*/
public function setCategory(?Category $category): self
{
$this->category = $category;
return $this;
}
/**
* @param Category|null $categoryChildren
*/
public function setCategoryChildren(?Category $categoryChildren): self
{
$this->categoryChildren = $categoryChildren;
return $this;
}
/**
* @return Category|null
*/
public function getCategoryChildren(): ?Category
{
return $this->categoryChildren;
}
/**
* @param Category|null $childCategoryChildren
*/
public function setChildCategoryChildren(?Category $childCategoryChildren): self
{
$this->childCategoryChildren = $childCategoryChildren;
return $this;
}
/**
* @return Category|null
*/
public function getChildCategoryChildren(): ?Category
{
return $this->childCategoryChildren;
}
}
這是我用于類別選擇的 ajax:
let $category = $('#create_ad_category');
let $childCategory = $('#create_ad_categoryChildren');
checkEmptySelect();
if ( $category.change() ) {
$category.change(function() {
let $form = $(this).closest('form');
let data = {};
data[$category.attr('name')] = $category.val();
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
complete: function(html) {
$('#create_ad_categoryChildren').replaceWith(
$(html.responseText).find('#create_ad_categoryChildren')
);
checkEmptySelect()
$('#create_ad_categoryChildren').prepend('<option value="" selected="selected"> '
'Select a subcategory of ' $category.find("option:selected").text() ' ...</option>');
}
});
});
}
function checkEmptySelect() {
if ( !$('#create_ad_categoryChildren').val() ) {
$('.subcategories').hide();
// $('.childCategories').hide();
} else {
$('.subcategories').show();
}
}
這是我的 categoryChildren 欄位的 ajax:
function getNewVal(item) {
let $form = $(this).closest('form');
let data = {};
data[$category.attr('name')] = $category.val();
data[$childCategory.attr('name')] = item.value;
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
complete: function(html) {
$('#create_ad_childCategoryChildren').replaceWith(
$(html.responseText).find('#create_ad_childCategoryChildren')
);
checkEmptySelect()
$('#create_ad_childCategoryChildren').prepend('<option value="" selected="selected"> '
'Select a subcategory of ' $('#create_ad_categoryChildren').find("option:selected").text() ' ...</option>');
}
});
}
我正在使用 Symfony 6.0。任何幫助將不勝感激,干杯。
uj5u.com熱心網友回復:
解決了; 我在 CreateAdType 類中將事件從 POST_SUBMIT 更改為 PRE_SUBMIT,并更改了偵聽器中的邏輯。此外,我不得不將函式 getNewVal() 中的 Ajax 型別從 $form.attr('method') 更改為 'POST',因為表單試圖呼叫 'GET' 而不是 'POST'。解決方案如下:
創建廣告型別.php:
//[...]
/**
* @param FormBuilderInterface $builder
*/
public function categoryChildrenListener(FormBuilderInterface $builder)
{
$formModifier = function (FormInterface $form, Category $category = null) {
$categoryChildren = null === $category ? [] : $this->categoryRepository->findBy(['parent' => $category]);
$form->add('categoryChildren', EntityType::class, [
'class' => Category::class,
'label' => 'Podkategorie',
'choice_label' => 'name',
'choices' => $categoryChildren,
'mapped' => false,
'attr' => [
'onChange' => "getNewVal(this);"
]
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
$formModifier($event->getForm(), $data->getCategory());
}
);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$ad = $event->getData();
$categoryId = array_key_exists('category', $ad) ? $ad['category'] : null;
$category = $this->categoryRepository->find($categoryId);
$formModifier($event->getForm(), $category);
}
);
}
/**
* @param FormBuilderInterface $builder
*/
public function childCategoryChildrenListener(FormBuilderInterface $builder)
{
$formChildCategoryModifier = function (FormInterface $form, Category $categoryChild = null) {
$childCategoryChildren = null === $categoryChild ? [] : $this->categoryRepository->findBy(['parent' => $categoryChild]);
$form->add('childCategoryChildren', EntityType::class, [
'class' => Category::class,
'label' => 'Podkategorie podkategorii',
'choice_label' => 'name',
'choices' => $childCategoryChildren,
'mapped' => false
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formChildCategoryModifier) {
$data = $event->getData();
$formChildCategoryModifier($event->getForm(), $data->getCategoryChildren());
}
);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($formChildCategoryModifier) {
$ad = $event->getData();
$childCategory = null;
if ( array_key_exists('categoryChildren', $ad) ) {
if ( $ad['categoryChildren'] !== '' ) {
$childCategoryId = $ad['categoryChildren'];
$childCategory = $this->categoryRepository->find($childCategoryId);
}
}
$formChildCategoryModifier($event->getForm(), $childCategory);
}
);
}
//[...]
Ajax 呼叫 categoryChildren 欄位:
function getNewVal(item) {
let $form = $(this).closest('form');
let data = {};
data[$category.attr('name')] = $category.val();
data[$childCategory.attr('name')] = item.value;
$.ajax({
url : $form.attr('action'),
type: "POST",
data : data,
complete: function(html) {
$('#create_ad_childCategoryChildren').replaceWith(
$(html.responseText).find('#create_ad_childCategoryChildren')
);
checkChildCategoryChildrenValue()
$('#create_ad_childCategoryChildren').prepend('<option value="" selected="selected"> '
'Wybierz podkategorie kategorii ' $('#create_ad_categoryChildren').find("option:selected").text() ' ...</option>');
}
});
}
function checkChildCategoryChildrenValue() {
if ( !$('#create_ad_childCategoryChildren').val() ) {
$('.childCategories').hide();
} else {
$('.childCategories').show();
}
}
我設法實作了這篇文章中的一些想法: How to add an Event Listener to a dynamic added field using Symfony Forms 希望它可以幫助某人節省時間和壓力:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/507532.html
