我想动态填写表格(见图片)
状态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));
}
})
});
}
});
}
国家和州的参数对应于两个第一select
。
此函数填充与所选国家/地区对应的状态select
。同样的机制适用于城市select
。
现在我想使用Symfony 4,这是我的表格:
<?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;
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'];
}
$states = json_decode(file_get_contents("js/states.json"), TRUE)['states'];
$statesChoices = array();
foreach($states as $state) {
$statesChoices[$state['name']] = $state['id'];
}
$cities = json_decode(file_get_contents("js/cities.json"), TRUE)['cities'];
$citiesChoices = array();
foreach($cities as $city) {
$citiesChoices[$city['name']] = $city['id'];
}
$builder
->add('country', ChoiceType::class, array(
'choices' => $countriesChoices
))
->add('area', ChoiceType::class, array(
'choices' => $statesChoices
))
->add('city', ChoiceType::class, array(
'choices' => array(
'Choose city' => $citiesChoices
))
->add('zip_code', TextType::class)
->add('street', TextType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Location::class,
));
}
}
这里的问题是我无法根据用户输入填写选项。 我也收到了OutOfMemoryException(cities.json中有超过40,000个城市)。
修改
在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,
));
}
}
填写表格后,我收到了消息:&#34;选择&#34; ...&#34;不存在或不是唯一的#34;。选择是指option
中所选城市的ID(select
的值)。
问题在于我无法弄清楚如何填充城市ChoiceType
?
答案 0 :(得分:1)
您需要根据之前选择的选项动态加载它们。方法与JS很相似。
您可以在官方文档中看到一个示例:Dynamic Generation for Submitted Forms。