2016-07-25 6 views
5

私のアプリケーションでは、いくつかのフォームフィールドがあり、多くのオプションがあります。私が経験した問題はthis questionと似ています。すべてのページロード時にすべてのオプションを取得して解析するのは高価です(Twigはすべてのオプションを何度も何度もレンダリングしますが、クライアントサイドキャッシュは使用できません)。この問題は、AJAX経由でブラウザにオプションを送信する方法を作りました。簡単なアプローチ:「Ajaxified」フォームの作成フィールドタイプ

  1. 可能であれば、AJAX(例:/countries.jsonを取得)とキャッシュを使用してすべてのオプションを取得します(キー値)。 (この場合、国名が頻繁に変更される可能性はあまりありません)
  2. DOMにオプションを挿入するには、selectize、select2などのプラグインを使用します。
  3. は、すべてのオプションを照会からsymfonyのを防ぐために

:-)速くフォームをお楽しみいただけます(不要:彼らは、AJAX経由で読み込んでいる)オプションを追加することにより、(フォームがロードされたとき、私はQueryBuildersetMaxResults(0)を追加しましたコントローラを介して)。はい、それはクルージングです。フォームを送信するときには、選択したオプションが存在するかどうかを検証し、制約をチェックする必要があるため、依然としてクエリが実行されます。

この機能を現在のEntityTypeに追加するcustom Form Field Typeを作成します。フォームのレンダリング中にオプションを読み込まず、選択したオプションが存在するかどうかを確認します。 dynamically modifying a formに関連するmanyexamplesが見つかりましたが、親フォームとは独立して1つのフォームフィールドのみを変更することに関する例は見つかりませんでした。

このようなフォームフィールドタイプを作成するにはどうすればよいですか?何が良い出発点ですか? EntityTypeChoiceType、または他の方法を拡張しますか?

私は既にSymfony 3.1を使用していますので、lazy loading of form choices(Symfony 3.2の新機能)を使用しても問題はありません。この新しい機能が私の問題に関連しているかどうかは不明です。

+0

[EntityTypeを拡張してAJAX呼び出しで余分な選択を可能にする]の可能な複製(http://stackoverflow.com/questions/30178424/extending-entitytype-to-allow-extra-choices-set-with-ajax-calls) ) – Alsatian

答えて

1

私はあなたがサーバー側で何をしているバンドル(Alsatian/FormBundle)を書きました。

  • How to avoid loading each entities by each form rendering

    キャッシュされたコンテンツとフォームフィールドを移入する方法
    abstract class AbstractExtensibleChoicesType extends AbstractRoutableType 
    { 
        public function configureOptions(OptionsResolver $resolver) 
        { 
         $resolver->setDefault('choices',array()); 
        } 
    } 
    

独自のロジックだ、私はお勧めします:のみを返すコントローラを作成します( HTMLとして):

<option value="1">Option 1</option> 
<option value="2">Option 2</option> 
MAXAGE設定コントローラで

:このURLをロードすると、あなたの選択フィールドにHTML結果を置くためにはJavaScript

/* 
* @Route(...) 
* @Cache(maxage=64000) 
*/ 
public function getOptionsAction(Request $request) // Home 
{ 
    $choices = $this->getDoctrine()->getManager()->getRepository //.... 

    return $this->render(/*...*/); 
} 

使用。

Select2のようなものを使用している場合:コントローラはJSONReponse()としてオプションを返すこともできます。このJSONはselect2 ajaxオプションから直接ロードできます(バンドルのドキュメントを参照してください)。

は(もPRE_SET_DATA編集するフォームを使用している場合)::フォームにPRE_SUBMITイベントを堤出さ選択肢を取得し、フィールドにこれらの選択肢を再注入します。

1

あなたのユースケースを考えると、オートコンプリートを使用するのが最善の方法です。ここではSymfony bundleと私は使用していると素晴らしいです。私はいくつかの機能を向上させるためにjavascript(autocompleter)を上書きしました。

+0

あなたの提案をありがとう、私はインスピレーションとしてそのバンドルを使用することができます。私は、クライアント側の検索がはるかに高速であるため、サーバー側の検索処理は欲しくない。 Twigを使用してJSON出力をレンダリングするため、コントローラの実装が嫌いです。なぜ?! –

+0

ええ、jsonをレンダリングするためにtwigを使用する代わりに、コントローラの中に結果の 'JsonResponse'を返すように書きました。 json出力のために小枝をレンダリングする必要はありません。 – Jeet

+0

私はそのようなバンドルが役に立つかどうかは確かではありません。ちょうどあなたのページ+初期コードにChosenライブラリを追加してください。ここでは "通常の"エンティティタイプを使用します。そして実際にパフォーマンスを向上させるためには、 "Ajax"オプションを使ってエントリをロードする必要があります。 – romaricdrigon

2

Ajaxコントローラオプションを使用したオートコンプリートは私にはうまく見えますが、別の(おそらくはより速い)オプションがあります:hincludeを通してフォームをレンダリングしてください。

hincludeは、ページの一部の読み込みを「延期」するのに使用されるJSライブラリで、Ajaxと思っています。 symfonyには統合サポート(official documentation)が付属しています。

ヨーヨーは、それを使用する方法:

    のは
  • があなたのページ(CF公式のGithub)このコード
  • 使用にhinclude.jsが含まformActionそれを呼びましょう、あなたのフォームが別のコントローラのアクションにレンダリング移動

  • あなたのフォームをレンダリングする:

    {{render_hinclude(コントローラー( '... :: form')、{'default': '読み込み中...「})}}

  • あなたはおそらく、あなたのオリジナルのコントローラのアクションで取り扱うフォームを維持するので、このような生成したフォームの 『アクション』を変更したいと思うでしょう:

    $フォーム=の$ this - > CreateFormの(新しいFormType()、$ obj、array( 'アクション' => $ this-> generateUrl( 'original_form_action')));

関連する問題