在不断研究找到一种使用 ajax 和 sonata 与 symfony4 一起使用动态下拉菜单的方法之后,我想分享我的解决方案,它实际上是如何为我工作的。
就我而言,我有一个区,这个区有不同的城市。我有一家公司,首先选择一个地区,然后根据该地区选择城市。
我做了什么:
为各地区创建您的实体
为城市创建您的实体
进入您的主类(在我的例子中,这是公司实体,并为地区和城市添加两个实体
/**
* @ORM\ManyToOne(targetEntity="App\Wdm\MainBundle\Entity\Model\Cities", inversedBy="id")
*/
private $city;
/**
* @ORM\ManyToOne(targetEntity="App\Wdm\MainBundle\Entity\Model\Districts", inversedBy="id")
*/
private $district;
更新数据库架构并使用一些示例数据填充城市和地区字段
进入 configureFormFields 函数中的 AdminClass 并添加以下内容(确保将“choice_label”选项与您所在地区或城市实体中的相应字段正确使用。
protected function configureFormFields(FormMapper $formMapper)
{ $formMapper
// Some other added fields
->add('district', EntityType::class, [
'choice_label' => 'name',
'class' => Districts::class,
'placeholder' => '',
])
->add('city', EntityType::class, [
'choice_label' => 'name',
'class' => Cities::class,
'placeholder' => '',
])
;
这应该已经很好用了。您现在应该能够拥有一个依赖字段。现在让我们来看看 AJAX 的魔力。
进入您的 AdminClass(与 configureFields-Class 相同)并添加以下内容
protected function configureRoutes(RouteCollection $collection)
{ $collection->add('reloadCities', 'reload-cities');
}
- 现在您有了可以从 ajax url 访问的路线。现在创建一个新的控制器类,无论您想要在哪里...
<?php
namespace App\Wdm\MainBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Sonata\AdminBundle\Controller\CRUDController as BaseController;
use App\Wdm\MainBundle\Entity\Model\Cities;
class CitiesController extends BaseController
{
public function reloadCitiesAction(Request $request)
{ $districtid = $request->request->get('id');
$cities = $this->getDoctrine()->getRepository(Cities::class)->findBy(array("district" => $districtid));
return $this->render("company/cities.html.twig", array("cities" => $cities));
}
}
...并且不要忘记在您的 services.yaml 中注册此控制器...
admin.company:
class: App\Wdm\MainBundle\Admin\CompanyAdmin
arguments:
- ~
- App\Wdm\MainBundle\Entity\Model\Company
- App\Wdm\MainBundle\Controller\CitiesController (THIS IS THE NEW ROW)
...最后是这个函数中调用的小模板...
// THIS IS THE cities.html.twig
{% for city in cities %}
<option value="{{ city.id }}">{{ city.name }}</option>
{% endfor %}
- 到目前为止,一切都很好。我们现在得到了从 ajax 调用获取数据并将其返回到您的奏鸣曲管理编辑表单的逻辑。现在唯一缺少的是sonata admin 编辑模板中所需的jquery 代码。
进入您的 AdminClass 并插入以下代码(例如在 configureFormFields 之前)
public function getTemplate($name)
{
switch ($name) {
case 'edit':
return 'company/cities_admin.html.twig';
break;
default:
return parent::getTemplate($name);
break;
}
}
现在我们创建这个 city_admin.html.twig 模板来覆盖默认模板
{% extends 'SonataAdminBundle:CRUD:edit.html.twig' %}
{% block form %}
{{ parent() }}
<script type="text/javascript">
$(document).ready(function () {
$("#ID_OF_YOUR_DISTRICT_SELECT_FIELD").change(function () {
$.ajax({
url: "{{ admin.generateUrl('reloadCities') }}",
data: {
'id': $(this).val(),
'uniquid': '{{ admin.uniqid }}'
},
method: 'POST',
success: function (html) {
$("#ID_OF_YOUR_CITY_SELECT_FIELD").html(html);
},
error: function (data) {
// more code
}
});
});
});
</script>
{% endblock %}
就是这样。应该像魅力一样发挥作用。