Ami*_*mit 29 ajax symfony symfony-sonata sonata-admin
我有一个商家实体,其中包含以下字段和关联: -
/**
* @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;
Run Code Online (Sandbox Code Playgroud)
标签和类别也有ManyToMany映射.所以我们有Tag_Category,Merchant_Tag,Merchant_Category映射表.
现在我想在这些字段上执行一些ajax.
我想让用户先选择主标签.在主标记的基础上,ajax将类别刷新为仅属于此标记的类别以及更多操作.
我怎样才能做到这一点?
谢谢!
Ami*_*mit 59
几个月前我就能完成这项工作.虽然a.aitboudad分享的内容是准确的.Symfony/Sonata的第一次定时器可能面临一些问题.
这是步骤.
1>扩展Sonata CRUD的edit.html.twig/ base_edit.html.twig.
为简单起见,我只使用后者.复制vendor/bundles/Sonata/AdminBundle/Resources/views/CRUD/base_edit.html.twig到MerchantAdminController对应的views文件夹中 -YourBundle/Resources/views/Merchant/base_edit.html.twig
2>我们需要告诉MerchantAdmin类使用此模板.所以我们覆盖SonataAdmin的getEditTemplate方法如下:
public function getEditTemplate()
{
return 'YourBundle:Merchant:base_edit.html.twig';
}
Run Code Online (Sandbox Code Playgroud)
3>接下来我们需要在我们的代码中编写Ajax功能base_edit.html.twig.标准Ajax包含以下内容:
3.1> - 在控制器中为Ajax请求创建一个Action我们主要想获得一个与特定标签相对应的类别ID列表.但很可能你只是使用Sonata的CRUD控制器.
定义扩展CRUDController的MerchantAdminController
<?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
{
}
Run Code Online (Sandbox Code Playgroud)
3.2> - 通过定义它来告诉管理服务使用这个新创建的控制器而不是默认的CRUDControllerYourBundle/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]
Run Code Online (Sandbox Code Playgroud)
请注意,第3个参数是控制器的名称.默认情况下,它将为null.
3.3> - 创建getCategoryOptionsFromTagAction控制器中命名的Action .您的Ajax调用将是此Action.
// 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);
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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 %}
Run Code Online (Sandbox Code Playgroud)
问题1:如何获取附加到所有Sonata元素的唯一ID
解决方案:使用admin变量可以访问所有Admin Class的属性,包括uniqId.请参阅有关如何使用它的代码.
问题2:如何在JS中获取路由器.
解决方案:默认情况下,Symfony2 Routing在JS中不起作用.您需要使用名为FOSJSRouting的包(如上所述)并公开路径.这样您也可以访问JS中的Router对象.
我稍微修改了我的解决方案,使这个例子更加清晰.如果您发现任何错误,请随时发表评论.
| 归档时间: |
|
| 查看次数: |
21103 次 |
| 最近记录: |