Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Sonata管理表单中使用Ajax?_Ajax_Symfony_Symfony Sonata_Sonata Admin - Fatal编程技术网

如何在Sonata管理表单中使用Ajax?

如何在Sonata管理表单中使用Ajax?,ajax,symfony,symfony-sonata,sonata-admin,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",

我有一个具有以下字段和关联的商户实体:-

/**
 * @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;
标记和类别也有很多映射。 因此,我们有标记\类别、商户\标记、商户\类别映射表

现在我想在这些字段上执行一些ajax

我想让用户先选择主标签。在主标记的基础上,ajax将类别刷新为仅属于该标记的类别以及其他一些操作

我怎样才能做到这一点


谢谢

几个月前,我成功地完成了这项工作。而a.aitboudad所分享的是准确的。第一次使用Symfony/Sonata的人可能会遇到一些难题

以下是步骤

1>扩展Sonata CRUD的
edit.html.twig
/
base\u 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类使用此模板。因此我们重写了SonatAdmin的
getEditTemplate
方法,如下所示:

public function getEditTemplate()
{
    return 'YourBundle:Merchant:base_edit.html.twig';
}
3>接下来,我们需要在
base\u edit.html.twig
中对Ajax功能进行编码。标准Ajax包括以下内容:

3.1>——在控制器中为Ajax请求创建一个操作 我们主要希望获得与特定标记对应的类别ID列表。但很可能你只是在使用索纳塔的积垢控制器

定义扩展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
{

}
请注意,第三个参数是控制器的名称。默认情况下,它将为null

3.3>——在控制器中创建名为
GetCategoryOptions fromTagAction
的操作。您的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.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 %}
{%block javascripts%}
{{parent()}}
$(文档).ready(函数(){
var primaryTag=$(“{admin.uniqId}}}u primaryTag”);
change(updateCategories());//将函数绑定到updateCategories
primaryTag.change();//手动触发以更新文档加载中的类别。
函数updateCategories(){
返回函数(){
var tagId=$(“{admin.uniqId}}}u primaryTag选项:选中”).val();
var primarycegory=$(“{admin.uniqId}}}u primarycegory”);
primaryCategory.empty();
primaryCategory.trigger(“李斯特:更新”);
var locale='{app.request.get(''u locale')}}';
var objectId='{admin.id(object)}}'
var url=Routing.generate('get_categories_from_tag',{'u locale':locale,'tagId':tagId,'gd_admin.merchant',id:objectId});
$.post(url,{tagId:tagId},函数(数据){
primaryCategory.empty().append(数据);
primaryCategory.trigger(“李斯特:更新”);
}“文本”);
primaryCategory.val(“选项:第一”).attr(“选定”,true);
};
}
});
{%endblock%}
明白1:如何获取附加到所有奏鸣曲元素的唯一ID

解决方案:使用admin变量,该变量将允许您访问所有admin类的属性,包括uniqId。请参阅有关如何使用它的代码

明白了2:如何在JS中获取路由器

解决方案:默认情况下,Symfony2路由在JS中不起作用。您需要使用名为FOSJSRouting(如上所述)的捆绑包并公开路由。这将允许您访问JS中的Router对象


我稍微修改了我的解决方案,使这个例子更清楚。如果您发现任何错误,请随时发表评论

在Amit和Lumbendil答案的第1步中,您应该进行更改

{% extends base_template %}
进入

如果你遇到这样的错误

Unable to find template "" in YourBundle:YourObject:base_edit.html.twig at line 34.  

非常详细的帖子,只是为了更新覆盖方式并使用Admin类中的编辑模板。
现在,您应该这样做:

// 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);
    }
}
或者将其注入所使用的服务定义中,以使Admin类尽可能干净:

// 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]]

在块javascripts中,您必须将
“liszt:updated”
更改为
“selected:updated”


希望它能帮助别人;)

很好的回答,很详细,很好!一个问题——为什么在ajax调用中需要使用FOSJSRouting?将tagId作为ajaxpost请求的一部分传递不是很容易吗?这样可以避免加载额外的bundle,FOSJSRouting就是访问路由器对象(Routing.generate(…)来生成路由的路径。如果它是一个普通的PHP项目,我们只需要从_tag.PHP中给出文件名-categories_。但是这里我们需要在控制器中调用一个操作。我这样做的方式是在我的管理类(TagAdmin)中添加路由:
$collection->add('addToGroup',$this->getRouterIdParameter()。/addToGroup')
,将此路由用于ajax url,如:
url:{{admin.generateUrl('addToGroup',{id':object.id}}}}}',
以及ajax定义中的额外数据参数:
data:'group='+$(this).preval('.group id').val(),
非常有用!您是否能够在加载时为现有商户筛选类别?我认为使用
MerchantAdmin::getEditTemplate()
不再有效。我必须将此更改为
MerchantAdmin::getTemplate($name)
,然后在
$name==='edit'
欢迎使用SO:)时返回我的自定义模板。您应该避免在
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]]