Json 如何使用Symfony表单动态填充下拉列表?
我想动态填写我的表格(见图) 状态Json 如何使用Symfony表单动态填充下拉列表?,json,forms,symfony,Json,Forms,Symfony,我想动态填写我的表格(见图) 状态select(html标记)由javascript函数用json文件填充: function onChangeCountries(countries, states) { $(countries).on("change", function(ev) { var countryId = $(this).val(); if (countryId != '') { states.empty();
select
(html标记)由javascript函数用json文件填充:
function onChangeCountries(countries, states) {
$(countries).on("change", function(ev) {
var countryId = $(this).val();
if (countryId != '') {
states.empty();
states.append('<option selected="true" disabled>Choose state</option>');
states.prop('selectedIndex', 0);
$.getJSON(statesUrl, function (data) {
$.each(data['states'], function (key, entry) {
if (entry.country_id == countryId) {
states.append($('<option></option>').attr('value', entry.id).text(entry.name));
}
})
});
}
});
}
这里的问题是,我无法根据用户输入填写选项。
我还收到一个OutOfMemoryException(cities.json中有40000多个城市)
编辑
在dlondero回答之后,我还没有解决我的问题,这是我新的LocationType
类:
<?php
// src/Form/LocationType.php
namespace App\Form;
use App\Entity\Location;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class LocationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$countries = json_decode(file_get_contents("js/countries.json"), TRUE)['countries'];
$countriesChoices = array();
foreach($countries as $country) {
$countriesChoices[$country['name']] = $country['id'];
}
$builder
->add('zip_code', TextType::class)
->add('street', TextType::class)
->add('country', ChoiceType::class, array(
'choices' => $countriesChoices
))
->add('area', ChoiceType::class, array(
'choices' => array()
))
->add('city', ChoiceType::class, array(
'choices' => array()
))
;
$formModifierStates = function (FormInterface $form, $countryId = null) {
$statesChoices = array();
if (null !== $countryId) {
$states = json_decode(file_get_contents("js/states.json"), TRUE)['states'];
foreach($states as $state) {
if ($countryId == $state['country_id']) {
$statesChoices[$state['name']] = $state['id'];
}
}
}
$form->add('area', ChoiceType::class, array(
'choices' => $statesChoices
));
};
$formModifierCities = function (FormInterface $form, $stateId = null) {
$citiesChoices = array();
if (null !== $stateId) {
$cities = json_decode(file_get_contents("js/cities.json"), TRUE)['cities'];
foreach($cities as $city) {
if ($stateId == $city['state_id']) {
$citiesChoices[$city['name']] = $city['id'];
}
}
}
$form->add('city', ChoiceType::class, array(
'choices' => $citiesChoices
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifierStates) {
$data = $event->getData(); // country id
$formModifierStates($event->getForm(), $data);
}
);
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifierCities) {
$data = $event->getData(); // state id
$formModifierCities($event->getForm(), $data);
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifierStates) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifierStates($event->getForm()->getParent(), $country);
}
);
$builder->get('area')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifierCities) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$state = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifierCities($event->getForm()->getParent(), $state);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Location::class,
));
}
}
您需要根据为上一次选择所做的选择动态加载它们。这种方法与使用JS的方法非常相似
您可以在官方文档中看到一个示例:。谢谢dlondero,我会看看这个。您添加了AJAX调用吗?检查上面链接的最后一个代码部分。为了获取数据和填充后续选择,需要添加一些绑定onchange事件的JS。是的,我添加了Ajax调用,当选择一个州时,它填充cityselect
,但我认为,我出现了提到的错误,原因是,LocationType
的buildForm
依赖字段应仅添加在事件侦听器中,而不是最初添加到生成器中。
<?php
// src/Form/LocationType.php
namespace App\Form;
use App\Entity\Location;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class LocationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$countries = json_decode(file_get_contents("js/countries.json"), TRUE)['countries'];
$countriesChoices = array();
foreach($countries as $country) {
$countriesChoices[$country['name']] = $country['id'];
}
$builder
->add('zip_code', TextType::class)
->add('street', TextType::class)
->add('country', ChoiceType::class, array(
'choices' => $countriesChoices
))
->add('area', ChoiceType::class, array(
'choices' => array()
))
->add('city', ChoiceType::class, array(
'choices' => array()
))
;
$formModifierStates = function (FormInterface $form, $countryId = null) {
$statesChoices = array();
if (null !== $countryId) {
$states = json_decode(file_get_contents("js/states.json"), TRUE)['states'];
foreach($states as $state) {
if ($countryId == $state['country_id']) {
$statesChoices[$state['name']] = $state['id'];
}
}
}
$form->add('area', ChoiceType::class, array(
'choices' => $statesChoices
));
};
$formModifierCities = function (FormInterface $form, $stateId = null) {
$citiesChoices = array();
if (null !== $stateId) {
$cities = json_decode(file_get_contents("js/cities.json"), TRUE)['cities'];
foreach($cities as $city) {
if ($stateId == $city['state_id']) {
$citiesChoices[$city['name']] = $city['id'];
}
}
}
$form->add('city', ChoiceType::class, array(
'choices' => $citiesChoices
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifierStates) {
$data = $event->getData(); // country id
$formModifierStates($event->getForm(), $data);
}
);
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifierCities) {
$data = $event->getData(); // state id
$formModifierCities($event->getForm(), $data);
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifierStates) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifierStates($event->getForm()->getParent(), $country);
}
);
$builder->get('area')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifierCities) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$state = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifierCities($event->getForm()->getParent(), $state);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Location::class,
));
}
}