1

私は3つのエンティティ(国、地域、都市)を持っています

namespace ****\****Bundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

class Country
{
  private $id;

  private $name;

  /**
   * @var integer $regions
   * 
   * @ORM\OneToMany(targetEntity="Region", mappedBy="Country")
   */
  protected $regions;
  //...
}

class Region
{
  private $id;

  private $name;

  /**
   * @var integer $country
   *
   * @Assert\Type(type="****\***Bundle\Entity\Country")
   * @ORM\ManyToOne(targetEntity="Country", inversedBy="regions")
   * @ORM\JoinColumn(name="country_id", referencedColumnName="id", nullable=false)
   */
  private $country;

  /**
   * @ORM\OneToMany(targetEntity="City", mappedBy="Region")
   */
  protected $cities;
}

class City
{
    private $id;

    private $name;

    /**
     * @var integer $region
     *
     * @Assert\Type(type="****\****Bundle\Entity\Region")
     * @ORM\ManyToOne(targetEntity="Region", inversedBy="cities")
     * @ORM\JoinColumn(name="region_id", referencedColumnName="id", nullable=false)
     */
    private $region;

    /**
     * @ORM\OneToMany(targetEntity="Company", mappedBy="City")
     */
    protected $companys;
//...
}

市のフォームクラスは次のとおりです。

namespace ****\****Bundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CityType extends AbstractType
{

  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    $builder
            ->add('name')
            ->add('region');
  }

  public function setDefaultOptions(OptionsResolverInterface $resolver)
  {
    $resolver->setDefaults(array(
        'data_class' => '****\****Bundle\Entity\City',
    ));
  }

  public function getName()
  {
    return 'city';
  }
}

これにより、名前の textBox とすべての領域が使用可能な SelectBox を持つ基本的な HTML5 フォームが作成されます。

私の質問は、最初の SelectBox を追加して、2 番目の SelectBox をフィルター処理し、地域の選択肢の数を減らすために国を選択できるようにする最善の方法は何ですか?

イベントリスナー? イベント ディスパッチャー コンポーネント ?

4

4 に答える 4

2

いいえ、EventListener と Event Dispatcher は、クライアント側ではなく、サーバーで発生するイベント用です。Javascript を使用する必要があります。選択ボックスの 1 つが変更されると、これは JavaScript 関数を起動し、AJAX 呼び出しを行い、その呼び出しの結果を他の選択ボックスに入力するか、JavaScript コードを使用して 2 番目のボックスに表示するオプションを選択する必要があります。

いくつかのアイデアについては、ここをご覧ください

于 2012-09-14T10:50:38.110 に答える
1

Carlos Granados が言ったように、基本的に 2 つのオプションがあります。

  1. 国をパラメーターとして受け取り、関連付けられた地域のリストを XML または JSON 形式で返す別の Symfony アクションを作成します。(JSON 応答を送信するために使用できますが、対応するクラスSymfony\Component\HttpFoundation\JsonResponseはありません)。ユーザーが現在選択されている項目を変更するたびに、 jQuery (またはその他の JS ライブラリまたはプレーン Javascript) を使用してサーバーに要求を送信しますXmlResponse。コールバック (Javascript で応答を取得したとき) で、領域選択ボックスを更新できます。jQuery Ajaxのドキュメントが興味深いかもしれません。

  2. すべての国とそれに関連する地域のリストを HTML コードに保存し (JSON を使用するか、ネイティブの Javascript 配列を生成できます)、ユーザーが国選択ボックスの値を変更するたびに、地域選択ボックス。

2 番目の方法では、すべての国とそれに関連付けられた地域を (データベースまたはテキスト ファイルから、またはそれらを保存した場所から) ロードし、JS で簡単に読み取れる形式でレンダリングする必要があるため、フォームの初期ロードの負荷が大きくなります。 .

ただし、最初の方法では、ユーザーが別の国を選択するたびにリクエストを送信する必要があります。さらに、別のアクションを実装する必要があります。

于 2012-09-14T11:01:24.737 に答える
0

私はフォームでこれを自分でやっています。フィールド(製品)を変更し、数量を測定できる単位を更新します。より簡単に適応させるために、パラメーター付きのマクロを使用しています。

マクロ:

{% macro javascript_filter_unit(event, selector) %}
<script>
    $(function(){
        $('#usersection')
                .on('{{ event }}', '{{ selector }}', function(e){
                    e.preventDefault();
                    if (!$(this).val()) return;
                    $.ajax({
                        $parent: $(this).closest('.child_collection'),
                        url: $(this).attr('data-url'),
                        type: "get",
                        dataType: "json",
                        data: {'id' : $(this).val(), 'repo': $(this).attr('data-repo'), parameter: $(this).attr('data-parameter')},
                        success: function (result) {
                            if (result['success'])
                            {
                                var units = result['units'];
                                this.$parent.find('.unit').eq(0).html(units);   
                            }
                        }
                    });
                })
    });

</script>

{% endmacro %}

ajax は配列を返します: array('success' => $value, 'units' => $html)。$html コードを使用して、変更する選択の代わりに配置します。もちろん、ajax 呼び出しの JavaScript コードは、フィールドに合わせて変更する必要があります。

通常どおりにマクロを呼び出します。

{% import ':Model/Macros:_macros.html.twig' as macros %}
{{ macros.javascript_filter_unit('change', '.unitTrigger') }}

したがって、私には 2 つの引数があります。イベント、多くの場合、選択の変更です。そして、その変更が ajax 呼び出しをトリガーするセレクターです。

それが役立つことを願っています。

于 2015-01-16T21:19:48.667 に答える
0

カルロス・グラナドスが言ったように、クライアント側のプログラミング、Javascript を使用する必要があります。私もあなたと同じ問題に遭遇し、私にとって完璧に機能する解決策を見つけました。ここに codepen のスニペットがあります。

    //-------------------------------SELECT CASCADING-------------------------//
    var currentCities=[];
// This is a demo API key that can only be used for a short period of time, and will be unavailable soon. You should rather request your API key (free)  from http://battuta.medunes.net/   
var BATTUTA_KEY="00000000000000000000000000000000"
    // Populate country select box from battuta API
    url="http://battuta.medunes.net/api/country/all/?key="+BATTUTA_KEY+"&callback=?";
    $.getJSON(url,function(countries)
    {
        console.log(countries);
      $('#country').material_select();
        //loop through countries..
        $.each(countries,function(key,country)
        {
            $("<option></option>")
                            .attr("value",country.code)
                            .append(country.name)
                            .appendTo($("#country"));

        }); 
        // trigger "change" to fire the #state section update process
        $("#country").material_select('update');
        $("#country").trigger("change");


    });

    $("#country").on("change",function()
    {

        countryCode=$("#country").val();

        // Populate country select box from battuta API
        url="http://battuta.medunes.net/api/region/"
        +countryCode
        +"/all/?key="+BATTUTA_KEY+"&callback=?";

        $.getJSON(url,function(regions)
        {
            $("#region option").remove();
            //loop through regions..
            $.each(regions,function(key,region)
            {
                $("<option></option>")
                                .attr("value",region.region)
                                .append(region.region)
                                .appendTo($("#region"));
            });
            // trigger "change" to fire the #state section update process
            $("#region").material_select('update');
            $("#region").trigger("change");

        }); 

    });
    $("#region").on("change",function()
    {

        // Populate country select box from battuta API
        countryCode=$("#country").val();
        region=$("#region").val();
        url="http://battuta.medunes.net/api/city/"
        +countryCode
        +"/search/?region="
        +region
        +"&key="
        +BATTUTA_KEY
        +"&callback=?";

        $.getJSON(url,function(cities)
        {
            currentCities=cities;
            var i=0;
            $("#city option").remove();

            //loop through regions..
            $.each(cities,function(key,city)
            {
                $("<option></option>")
                                .attr("value",i++)
                                .append(city.city)
                        .appendTo($("#city"));
            });
            // trigger "change" to fire the #state section update process
            $("#city").material_select('update');
            $("#city").trigger("change");

        }); 

    }); 
    $("#city").on("change",function()
    {
      currentIndex=$("#city").val();
      currentCity=currentCities[currentIndex];
      city=currentCity.city;
      region=currentCity.region;
      country=currentCity.country;
      lat=currentCity.latitude;
      lng=currentCity.longitude;
      $("#location").html('<i class="fa fa-map-marker"></i> <strong> '+city+"/"+region+"</strong>("+lat+","+lng+")");
    });
   //-------------------------------END OF SELECT CASCADING-------------------------//
于 2017-07-13T21:40:52.697 に答える