dpp10181 2015-06-22 18:17
浏览 42
已采纳

Sonata Admin Bundle:刷新同一实体类型的多个sonata_model_type输入?

I have two entities Location and Person. Person has four many to one relationships to the Location entity.

A Person has one of each of the following locations:

  • Home Town
  • List item
  • Current Town
  • Departure Arrival

Like this:

class Person {

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="notes", type="string", length=255, nullable=false)
 */
private $name;

/**
 * @ORM\ManyToOne(targetEntity="Location", inversedBy="locationHomeTowns")
 * @ORM\JoinColumn(name="home_town_location_id", referencedColumnName="id", onDelete="SET NULL")
 */
protected $locationHomeTown;

/**
 * @ORM\ManyToOne(targetEntity="Location", inversedBy="locationCurrentTowns")
 * @ORM\JoinColumn(name="current_town_location_id", referencedColumnName="id", onDelete="SET NULL")
 */
protected $locationCurrentTown;

/**
 * @ORM\ManyToOne(targetEntity="Location", inversedBy="locationDepartures")
 * @ORM\JoinColumn(name="departure_location_id", referencedColumnName="id", onDelete="SET NULL")
 */
protected $locationDeparture;

/**
 * @ORM\ManyToOne(targetEntity="Location", inversedBy="locationArrivals")
 * @ORM\JoinColumn(name="arrival_location_id", referencedColumnName="id", onDelete="SET NULL")
 */
protected $locationArrival;
…
}

class Location {

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="latitude", type="decimal", scale=12, precision=18, nullable=false)
 */
private $latitude;

/**
 * @var string
 *
 * @ORM\Column(name="longitude", type="decimal", scale=12, precision=18, nullable=false)
 */
private $longitude;

/**
 * @var string
 *
 * @ORM\Column(name="notes", type="string", length=255, nullable=false)
 */
private $name;

/**
 * @ORM\OneToMany(targetEntity="Person", mappedBy="locationHomeTown", cascade={"persist"}, orphanRemoval=false)
 */
protected $locationHomeTowns;

/**
 * @ORM\OneToMany(targetEntity="Person", mappedBy="locationCurrentTown", cascade={"persist"}, orphanRemoval=false)
 */
protected $locationCurrentTowns;

/**
 * @ORM\OneToMany(targetEntity="Person", mappedBy="locationDeparture", cascade={"persist"}, orphanRemoval=false)
 */
protected $locationDepartures;

/**
 * @ORM\OneToMany(targetEntity="Person", mappedBy="locationArrival", cascade={"persist"}, orphanRemoval=false)
 */
protected $locationArrivals;
…
}

I have setup the admin classes both entities as follows:

class LocationAdmin extends Admin {
…
/**
 * @param FormMapper $formMapper
 */
protected function configureFormFields(FormMapper $formMapper) {
    $formMapper
            ->add('longitude', null, array('attr' => array(
                    'placeholder' => 'decimal degrees e.g. 51.5072',
        )))
            ->add('latitude', null, array('attr' => array(
                    'placeholder' => 'decimal degrees e.g. -0.1275',
        )))
            ->add('name')
        ;
    }
…
}

class ExileAdmin extends Admin {
…
/**
 * @param FormMapper $formMapper
 */
protected function configureFormFields(FormMapper $formMapper) {
    $formMapper
            ->add('name')
            ->add('locationHomeTown', 'sonata_type_model', array(
                'required' => false
           ))
           ->add('locationCurrentTown', 'sonata_type_model', array(
                'required' => false
           ))
           ->add('locationDeparture', 'sonata_type_model', array(
                'required' => false
           ))
           ->add('locationArrival', 'sonata_type_model', array(
                'required' => false
           ))
           ;
    }
…
}

I have set the locations as sonata_type_model in the person form to allow me to add new locations whilst editing the person entity. This works as expected for each input, however only that list of locations updates. This means I have to save the whole Person form if I need to use this new location in one of the other location fields on the form.

Is there a way to have all of the location input widgets update when I add a new location to one of the other inputs?

For example, if I currently have London, Paris and Berlin stored in the database and I add Rome to Home Town I would like the form input widgets for Current Town, Departure and Arrival to update too. If I then add Dublin to Current Town I would like Home Town, Departure and Arrival to update too, and so on for Departure and Arrival.

  • 写回答

1条回答 默认 最新

  • dongzhan7909 2015-06-23 01:14
    关注

    What you need to do is catch the sonata-admin-append-form-element javascript event when the new Location presisted and sync all other select element's options with the triggered one.

    First override Sonata's form admin fields; this will generate the event handling javascript block for each element in your form.

    I know this is not the most elegant way to use "select" selectors and filter appropriate elements in the for loop but this may guide you.

    YourBundle/resources/views/Form/form_admin_fields.html.twig

    {% extends 'SonataAdminBundle:Form:form_admin_fields.html.twig' %}
    
    {% block sonata_admin_orm_many_to_one_widget %}
    
        {% include 'SonataDoctrineORMAdminBundle:CRUD:edit_orm_many_to_one.html.twig' %}
    
        <script type="text/javascript"> 
    
        /*The event fires twice after appending Location element, 
          so I remove the listener at first*/
        $('div[id$={{form.vars['id']}}]').off('sonata-admin-append-form-element');
    
        $('div[id$={{form.vars['id']}}]').on('sonata-admin-append-form-element', function(event) {
            //I loop every children of parent form
            {% for element in form.parent.children %}
                if({{element.vars['id']}}!={{form.vars['id']}}) {
                    /*Copy the options from the current select 
                    element with the most update values*/
                    var opts = $('#{{form.vars['id']}} > option').clone();
                    //console.log($('select[id$={{element.vars["id"]}}]'));
                    /* I add the most updated options 
                    to other select elements.
                    */
                    $('select[id$={{element.vars["id"]}}]').empty();
                    $('select[id$={{element.vars["id"]}}]').append(opts);
    
    
                }
            {% endfor %}
    
        });
    
        </script>
    
    {% endblock %}
    

    Then override your ExileAdmin getFormTheme method;

      public function getFormTheme()
      {
          return array_merge(
              parent::getFormTheme(),
              array('YourBundle:Form:form_admin_fields.html.twig')
          );
      }
    

    I guess that's all now when you persist a Location all select elements are synced with the most updated one.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用