我有3个实体(国家,地区,城市)
namespace ****\****Bundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
class Country
{
private $id;
private $name;
/**
* @var integer $regions
*
* @ORM\OneToMany(targetEntity="Region", mappedBy="Country")
*/
protected $regions;
//...
}
class Region
{
private $id;
private $name;
/**
* @var integer $country
*
* @Assert\Type(type="****\***Bundle\Entity\Country")
* @ORM\ManyToOne(targetEntity="Country", inversedBy="regions")
* @ORM\JoinColumn(name="country_id", referencedColumnName="id", nullable=false)
*/
private $country;
/**
* @ORM\OneToMany(targetEntity="City", mappedBy="Region")
*/
protected $cities;
}
class City
{
private $id;
private $name;
/**
* @var integer $region
*
* @Assert\Type(type="****\****Bundle\Entity\Region")
* @ORM\ManyToOne(targetEntity="Region", inversedBy="cities")
* @ORM\JoinColumn(name="region_id", referencedColumnName="id", nullable=false)
*/
private $region;
/**
* @ORM\OneToMany(targetEntity="Company", mappedBy="City")
*/
protected $companys;
//...
}
这是我的城市表格类:
namespace ****\****Bundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('region');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => '****\****Bundle\Entity\City',
));
}
public function getName()
{
return 'city';
}
}
这会创建一个基本的HTML5表单,其中包含名称的textBox和一个所有区域都可用的SelectBox。
我的问题是添加第一个SelectBox的最佳方法是什么,它允许我选择国家以过滤第二个SelectBox并减少Region的选择数量?
EventListener? 事件调度程序组件?
答案 0 :(得分:2)
否,EventListener和Event调度程序用于在服务器上发生的事件,而不是客户端上发生的事件。你需要使用Javascript。当其中一个选择框发生变化时,这应该触发一个javascript函数并进行一次AJAX调用并用该调用的结果填充另一个选择框,或者使用一些javascript代码来选择在第二个框中显示哪些选项。
查看here了解一些想法
答案 1 :(得分:1)
正如Carlos Granados所说,你基本上有两种选择:
创建一个单独的Symfony操作,该操作将一个国家/地区作为参数,并以XML或JSON格式返回关联区域的列表。 (您可以使用Symfony\Component\HttpFoundation\JsonResponse
发送JSON响应,但是没有相应的XmlResponse
类。每当用户更改当前选定的项目时,使用jQuery(或任何其他JS库甚至普通Javascript)向服务器发送请求。在回调中(当您在Javascript中检索响应时),您可以更新区域选择框。您可能会发现jQuery Ajax有趣的文档。
您可以在HTML代码中存储所有国家/地区及其相关区域的列表(您可以使用JSON或生成本机Javascript数组),每当用户更改国家/地区选择框的值时,您只需更换区域中的区域列表选择框。
第二种方法对表单的初始加载负载较重,因为必须加载所有国家及其相关区域(从数据库或文本文件或存储它们的任何位置)并以易于格式呈现由JS阅读。
然而,第一种方法必须在每次用户选择其他国家/地区时发送请求。此外,您还必须实施其他操作。
答案 2 :(得分:0)
我自己在表格上这样做。 我更改了一个字段(一个产品),并且更新了可以测量数量的单位。 我正在使用带参数的宏来更容易地调整它。
宏:
{% macro javascript_filter_unit(event, selector) %}
<script>
$(function(){
$('#usersection')
.on('{{ event }}', '{{ selector }}', function(e){
e.preventDefault();
if (!$(this).val()) return;
$.ajax({
$parent: $(this).closest('.child_collection'),
url: $(this).attr('data-url'),
type: "get",
dataType: "json",
data: {'id' : $(this).val(), 'repo': $(this).attr('data-repo'), parameter: $(this).attr('data-parameter')},
success: function (result) {
if (result['success'])
{
var units = result['units'];
this.$parent.find('.unit').eq(0).html(units);
}
}
});
})
});
</script>
{% endmacro %}
ajax返回一个数组:array('success'=&gt; $ value,'units'=&gt; $ html)。您使用$ html代码并将其替换为您要更改的选择。 当然,需要修改ajax调用的javascript代码以匹配您的字段。
您可以像平常一样调用宏:
{% import ':Model/Macros:_macros.html.twig' as macros %}
{{ macros.javascript_filter_unit('change', '.unitTrigger') }}
所以我有两个参数:事件,通常是一个选择的变化。和一个选择器,其更改触发ajax调用。
我希望有所帮助。
答案 3 :(得分:0)
正如Carlos Granados所说,你必须使用客户端编程:Javascript。 我也遇到了和你一样的问题,并提出了一个对我来说非常有效的解决方案,这里是the snippet on codepen,你可以从(Cascade Ajax Selects)获得灵感
//-------------------------------SELECT CASCADING-------------------------//
var currentCities=[];
// This is a demo API key that can only be used for a short period of time, and will be unavailable soon. You should rather request your API key (free) from http://battuta.medunes.net/
var BATTUTA_KEY="00000000000000000000000000000000"
// Populate country select box from battuta API
url="http://battuta.medunes.net/api/country/all/?key="+BATTUTA_KEY+"&callback=?";
$.getJSON(url,function(countries)
{
console.log(countries);
$('#country').material_select();
//loop through countries..
$.each(countries,function(key,country)
{
$("<option></option>")
.attr("value",country.code)
.append(country.name)
.appendTo($("#country"));
});
// trigger "change" to fire the #state section update process
$("#country").material_select('update');
$("#country").trigger("change");
});
$("#country").on("change",function()
{
countryCode=$("#country").val();
// Populate country select box from battuta API
url="http://battuta.medunes.net/api/region/"
+countryCode
+"/all/?key="+BATTUTA_KEY+"&callback=?";
$.getJSON(url,function(regions)
{
$("#region option").remove();
//loop through regions..
$.each(regions,function(key,region)
{
$("<option></option>")
.attr("value",region.region)
.append(region.region)
.appendTo($("#region"));
});
// trigger "change" to fire the #state section update process
$("#region").material_select('update');
$("#region").trigger("change");
});
});
$("#region").on("change",function()
{
// Populate country select box from battuta API
countryCode=$("#country").val();
region=$("#region").val();
url="http://battuta.medunes.net/api/city/"
+countryCode
+"/search/?region="
+region
+"&key="
+BATTUTA_KEY
+"&callback=?";
$.getJSON(url,function(cities)
{
currentCities=cities;
var i=0;
$("#city option").remove();
//loop through regions..
$.each(cities,function(key,city)
{
$("<option></option>")
.attr("value",i++)
.append(city.city)
.appendTo($("#city"));
});
// trigger "change" to fire the #state section update process
$("#city").material_select('update');
$("#city").trigger("change");
});
});
$("#city").on("change",function()
{
currentIndex=$("#city").val();
currentCity=currentCities[currentIndex];
city=currentCity.city;
region=currentCity.region;
country=currentCity.country;
lat=currentCity.latitude;
lng=currentCity.longitude;
$("#location").html('<i class="fa fa-map-marker"></i> <strong> '+city+"/"+region+"</strong>("+lat+","+lng+")");
});
//-------------------------------END OF SELECT CASCADING-------------------------//