当前位置: 首页 > 面试题库 >

如何在Sonata Admin表单中使用Ajax?

高运诚
2023-03-14
问题内容

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

/**
 * @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;

标签和类别也具有ManyToMany映射。因此,我们有Tag_Category,Merchant_Tag,Merchant_Category映射表。

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

我想允许用户首先选择主要标签。在主要标签的基础上,ajax将类别刷新为仅属于该标签的类别,并进行其他一些操作。

我该如何实现?

谢谢!


问题答案:

几个月前,我能够完成这项工作。尽管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';
}

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
{

}

3.2 >
-通过在中定义它,告诉您的Admin服务使用此新创建的控制器而不是默认的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]

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

3.3 > -
getCategoryOptionsFromTagAction在控制器中创建一个名为Action的动作。您的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: 如何获取附加到所有Sonata元素的唯一ID

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

陷阱2: 如何在JS中获取路由器。

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

我对解决方案进行了一些修改,以使此示例更加清晰。如果您发现任何错误,请随时发表评论。



 类似资料:
  • 问题内容: 我是Liferay门户网站的新手。我已经在liferay中开发了一个portlet进行演示。在此示例中,我使用了portlet间的通信。我正在做的是:-我有一个搜索portlet,其中有一个要搜索的文本字段。当我单击搜索按钮时,它将从数据库中获取数据,并使用另一个portlet中包含的搜索显示该数据。我为此项目使用了ProcessEvent和ActionEvent批注。 现在我想要的是

  • 问题内容: 这是我的表单和onClick方法。我想在按下键盘的Enter按钮时执行此方法。怎么样 ? 注意: 没有jquery被赞赏。 问题答案: 更改为。删除。反而做。这应该可以单击按钮并按回车键。

  • 我有一个使用Xamarin.Forms的应用程序,针对IOS,Android和WP 8。 我的应用中需要推送通知功能。 我看过<code>pushsharp</code>演示,它似乎很有前途。但我看到的所有代码都是针对每个平台分别编写的。 我希望这件事能在法庭上进行。Forms项目,在App.cs中的某个地方,这样我就不需要重复注册设备的代码,也不需要处理应该如何处理推送通知。 任何帮助都将不胜感

  • 问题内容: 因此,我有一堆段落元素是从数据库动态填充的。我已经使元素内容可编辑。我现在想通过标准表单提交将编辑提交回数据库。有没有一种方法可以将contenteditable元素发布回去? 问题答案: 您必须使用javascript的一种或另一种方式,它不能像textarea之类的那样用作“标准”表单元素。如果愿意,可以在表单内创建一个隐藏的文本区域,然后在表单的onsubmit函数中将可编辑内容

  • 问题内容: 我正在IntelliJ IDEA 9中用一个按钮创建一个简单的GUI表单。用该表单创建的类不是JFrame或任何其他swing类。如何在源代码中调用表单? 问题答案: 只需进入与您的表单关联的类,按+ 并选择“ Form main()”即可。 资源: GUI设计器基础