29

次のフィールドと関連付けを持つ Merchant エンティティがあります。

/**
 * @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 は、このタグに属するものだけにカテゴリを更新し、さらにいくつかの操作を行います。

どうすればこれを達成できますか?

ありがとう!

4

4 に答える 4

61

数か月前にこの作業を行うことができました。a.aitboudad が共有した内容は正確ですが。Symfony/Sonata を初めて使用する人が直面する可能性のある落とし穴がいくつかあります。

手順は次のとおりです。

1> Sonata CRUD のedit.html.twig/を拡張しbase_edit.html.twigます。 簡単にするために、後者のみを使用します。vendor/bundles/Sonata/AdminBundle/Resources/views/CRUD/base_edit.html.twigMerchantAdminController に対応するビュー フォルダーにコピーします。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 のリストを取得する必要があります。しかし、ほとんどの場合、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> -- で定義することにより、デフォルトの 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 番目の引数がコントローラーの名前であることに注意してください。デフォルトでは null でした。

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:すべての Sonata 要素に追加される一意の ID を取得する方法

解決策: uniqId を含むすべての管理クラスのプロパティにアクセスできる管理変数を使用します。使用方法についてはコードを参照してください。

落とし穴 2: JS でルーターを取得する方法。

解決策:デフォルトでは、Symfony2 ルーティングは JS では機能しません。FOSJSRouting (上記で説明) というバンドルを使用して、ルートを公開する必要があります。これにより、JS 内の Router オブジェクトにもアクセスできるようになります。

この例をより明確にするために、ソリューションを少し変更しました。何かおかしなところがありましたら、お気軽にコメントください。

于 2012-05-28T11:08:31.333 に答える
4

アミットとルンベンディルの回答のステップ1で、変更する必要があります

{% extends base_template %}

の中へ

{% extends 'SonataAdminBundle::standard_layout.html.twig' %}

次のようなエラーが発生した場合

Unable to find template "" in YourBundle:YourObject:base_edit.html.twig at line 34.  
于 2014-03-31T12:47:42.840 に答える
2

ブロック JavaScript では、次のように変更"liszt:updated"する必要があります。"chosen:updated"

それが誰かを助けることを願っています;)

于 2016-06-24T09:46:58.457 に答える