我有以下字段和关联商家实体: -
/**
* @ORM\ManyToMany(targetEntity="Category", inversedBy="merchants")
*/
public $categories;
/**
* @ORM\ManyToMany(targetEntity="Tag", inversedBy="merchants")
*/
public $tags;
/**
* @ORM\ManyToOne(targetEntity="Category", inversedBy="merchants")
*/
protected $primaryCategory;
/**
* @ORM\ManyToOne(targetEntity="Tag", inversedBy="merchants")
*/
protected $primaryTag;
标签和分类也有一个多对多的映射。 因此,我们有Tag_Category,Merchant_Tag,Merchant_Category映射表。
现在,我想在这些领域进行一些Ajax。
我想允许用户首先选择的主要标记。 在主标签的基础上,阿贾克斯刷新类别,只有那些属于这个标签以及一些更多的操作。
我怎样才能做到这一点?
谢谢!
我是能够使这项工作在几个月前。 虽然什么a.aitboudad已经共享是准确的。 有一些疑难杂症的,与Symfony的/索纳塔初来乍可能面临。
下面是步骤。
1>扩展索纳塔CRUD的edit.html.twig
/ base_edit.html.twig
。 为简单起见,我将只使用后者。 复制vendor/bundles/Sonata/AdminBundle/Resources/views/CRUD/base_edit.html.twig
到视图文件夹对应于MerchantAdminController - YourBundle/Resources/views/Merchant/base_edit.html.twig
2>我们需要告诉我们的MerchantAdmin类中使用这个模板。 所以,我们覆盖SonataAdmin的getEditTemplate
这样的方法:
public function getEditTemplate()
{
return 'YourBundle:Merchant:base_edit.html.twig';
}
3>接下来,我们需要在我们编写Ajax功能 base_edit.html.twig
。 标准的AJAX包括以下内容:
3.1> -创建控制器为Ajax请求,我们主要是想获得对应于特定的标签类别ID列表的动作。 但最有可能你只是用索纳塔的CRUD控制器。
定义你的MerchantAdminController延伸CRUDController
<?php
namespace GD\AdminBundle\Controller;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use GD\AdminBundle\Entity\Merchant;
class MerchantAdminController extends Controller
{
}
3.2> -告诉你的管理服务由定义它使用这个新创建的控制器,而不是默认CRUDController YourBundle/Resources/config/services.yml
gd_admin.merchant:
class: %gd_admin.merchant.class%
tags:
- { name: sonata.admin, manager_type: orm, group: gd_merchant, label: Merchants }
arguments: [null, GD\AdminBundle\Entity\Merchant, GDAdminBundle:MerchantAdmin]
请注意,第三个参数是你的控制器的名称。 默认情况下,它会一直空。
3.3> -创建一个名为动作getCategoryOptionsFromTagAction
在你的控制器。 你的Ajax调用将是这个动作。
// route - get_categories_from_tag
public function getCategoryOptionsFromTagAction($tagId)
{
$html = ""; // HTML as response
$tag = $this->getDoctrine()
->getRepository('YourBundle:Tag')
->find($tagId);
$categories = $tag->getCategories();
foreach($categories as $cat){
$html .= '<option value="'.$cat->getId().'" >'.$cat->getName().'</option>';
}
return new Response($html, 200);
}
3.4> -创建在相应的路由app/config/routing.yml
。 请记住,如果你使用的是FOSJsRoutingBundle暴露你的路线(否则你必须硬编码这是不是一个好主意)。
get_categories_from_tag:
pattern: /{_locale}/admin/gd/admin/merchant/get-categories-from-tag/{tagId}
defaults: {_controller: GDAdminBundle:MerchantAdmin:getCategoryOptionsFromTag}
options:
expose: true
3.5> -使Ajax请求,并使用响应
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
$(document).ready(function(){
var primaryTag = $("#{{ admin.uniqId }}_primaryTag");
primaryTag.change(updateCategories()); // Bind the function to updateCategories
primaryTag.change(); // Manual trigger to update categories in Document load.
function updateCategories(){
return function () {
var tagId = $("#{{ admin.uniqId }}_primaryTag option:selected").val();
var primaryCategory = $("#{{ admin.uniqId }}_primaryCategory");
primaryCategory.empty();
primaryCategory.trigger("liszt:updated");
var locale = '{{ app.request.get('_locale') }}';
var objectId = '{{ admin.id(object) }}'
var url = Routing.generate('get_categories_from_tag', { '_locale': locale, 'tagId': tagId, _sonata_admin: 'gd_admin.merchant', id: objectId });
$.post(url, { tagId: tagId }, function(data){
primaryCategory.empty().append(data);
primaryCategory.trigger("liszt:updated");
},"text");
primaryCategory.val("option:first").attr("selected", true);
};
}
});
</script>
{% endblock %}
疑难杂症1:如何获得追加到所有索纳塔元素的唯一ID
解决方案:使用admin变量,这将给到管理类的所有属性,包括uniqId你的访问。 查看如何使用它的代码。
疑难杂症2:如何让你的JS路由器。
解决方案:默认情况下,Symfony2的路由不JS工作。 你需要使用一个名为FOSJSRouting束(如上所述)和暴露的路线。 这会给你访问路由器对象的JS内了。
我已经修改了我的解决方案稍微使这个例子更清晰。 如果您发现任何错误,请随时发表评论。
在阿米特和Lumbendil的步骤1回答你应该改变
{% extends base_template %}
成
{% extends 'SonataAdminBundle::standard_layout.html.twig' %}
如果你得到一个错误
Unable to find template "" in YourBundle:YourObject:base_edit.html.twig at line 34.
非常详细的帖子,只是为了更新覆盖的方式,并在管理类使用编辑模板。
现在,你应该做的是这样的:
// src/AppBundle/Admin/EntityAdmin.php
class EntityAdmin extends Admin
{
public function getTemplate($name)
{
if ( $name == "edit" )
{
// template 'base_edit.html.twig' placed in app/Resources/views/Entity
return 'Entity/base_edit.html.twig' ;
}
return parent::getTemplate($name);
}
}
或所使用的服务定义注入它提供的方法 ,以保持管理类的清洁剂尽可能:
// app/config/services.yml
app.admin.entity:
class: AppBundle\Admin\EntityAdmin
arguments: [~, AppBundle\Entity\Entity, ~]
tags:
- {name: sonata.admin, manager_type: orm, group: "Group", label: "Label"}
calls:
- [ setTemplate, [edit, Entity/base_edit.html.twig]]
在块JavaScript的,你必须改变"liszt:updated"
到"chosen:updated"
希望它可以帮助别人;)