我有两个实体Location和Person。Person与Location实体有四种多对一关系。
一个人有以下每个位置之一:
- 家乡
- 列出项目
- 当前城镇
- 离港到达
像这样:
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;
…
}
我已经设置了如下两个实体的管理类:
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
))
;
}
…
}
我在person表单中将位置设置为sonata_type_model,以便在编辑person实体时添加新位置。这对于每个输入都是按预期工作的,但是只有位置列表会更新。这意味着,如果我需要在表单上的其他位置字段中使用这个新位置,我必须保存整个人员表单。
当我将一个新的位置添加到其他输入时,有没有一种方法可以更新所有的位置输入小部件?
例如,如果我目前在数据库中存储了伦敦、巴黎和柏林,并将罗马添加到家乡,我希望当前城市、出发和到达的表单输入小部件也能更新。如果我将都柏林添加到当前城镇,我希望家乡、出发和到达也进行更新,依此类推,以更新离开以及抵达。
您需要做的是在新位置预存在时捕获sonata-admin-append-form-element
javascript事件,并将所有其他select元素的选项与触发的选项同步。
首先覆盖Sonata的表单管理字段;这将为表单中的每个元素生成事件处理javascript块。
我知道这不是在for循环中使用"选择"选择器和过滤适当元素的最优雅的方法,但这可能会对您有所指导。
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 %}
然后覆盖您的ExileAdmin getFormTheme方法;
public function getFormTheme()
{
return array_merge(
parent::getFormTheme(),
array('YourBundle:Form:form_admin_fields.html.twig')
);
}
我想现在就是这样了,当你坚持一个位置时,所有选择的元素都会与最新的元素同步。