私は次のフィールドと関連付けを持つマーチャントエンティティを持っています:-
/**
* @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
を拡張します。簡単にするために、後者のみを使用します。 MerchantAdminControllerに対応するビューフォルダにvendor/bundles/Sonata/AdminBundle/Resources/views/CRUD/base_edit.html.twig
をコピーします-YourBundle/Resources/views/Merchant/base_edit.html.twig
2>このテンプレートを使用するようにMerchantAdminクラスに指示する必要があります。したがって、SonataAdminのgetEditTemplate
メソッドを次のようにオーバーライドします。
public function getEditTemplate()
{
return 'YourBundle:Merchant:base_edit.html.twig';
}
3>次に、base_edit.html.twig
にAjax機能をコーディングする必要があります。標準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>-YourBundle/Resources/config/services.yml
で定義して、デフォルトのCRUDControllerの代わりにこの新しく作成されたコントローラーを使用するように管理サービスに指示します
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 %}
Gotcha 1:すべてのSonata要素に追加される一意のIDを取得する方法
解決策:uniqIdを含むすべての管理クラスのプロパティへのアクセスを提供する管理変数を使用します。それを使用する方法のコードを参照してください。
Gotcha 2:JSでルーターを取得する方法。
解決策:デフォルトでは、Symfony2ルーティングはJSで機能しません。 FOSJSRouting(上記で説明)と呼ばれるバンドルを使用し、ルートを公開する必要があります。これにより、JS内のルーターオブジェクトにもアクセスできます。
この例をより明確にするために、ソリューションを少し変更しました。何かお気づきの点がございましたら、お気軽にコメントください。
オーバーライドの方法を更新し、Adminクラスのeditテンプレートを使用するための非常に詳細な投稿。
今、あなたはそれをこのようにすべきです:
// 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]]
アミットとルンベンディルの回答のステップ1では、変更する必要があります
{% extends base_template %}
に
{% extends 'SonataAdminBundle::standard_layout.html.twig' %}
次のようなエラーが発生した場合
Unable to find template "" in YourBundle:YourObject:base_edit.html.twig at line 34.
ブロックJavaScriptで、"liszt:updated"
を"chosen:updated"
に変更する必要があります
それが誰かを助けることを願っています;)