我有一个实体Lexeme,它包含语言和音素实体。
在我的表单类型中,我希望Phoneme选项有所不同,具体取决于为Lexeme选择的语言实体。
问题是当我动态更新表单时,会显示正确的音素,但不会从数据库填充它们:即属于数据库中Lexeme的那些音素在动态加载的表单中不会显示为已检查。
Lexeme控制器:
public function editAction(Request $request, $id)
{
$lexeme = $this->getDoctrine()
->getRepository('Aleph2OmegaTranscriptionBundle:Lexeme')
->find($id);
$query = $this->getDoctrine()
->getRepository('Aleph2OmegaTranscriptionBundle:Lexeme')
->createQueryBuilder('l')
->where('l.id > :thisId')
->setParameter('thisId', $id)
->setMaxResults(1)
->getQuery();
$nextLexeme = $query->getResult();
$query = $this->getDoctrine()
->getRepository('Aleph2OmegaTranscriptionBundle:Lexeme')
->createQueryBuilder('l')
->where('l.id < :thisId')
->setParameter('thisId', $id)
->setMaxResults(1)
->getQuery();
$previousLexeme = $query->getResult();
if ( count($nextLexeme) < 1 ) {
$query = $this->getDoctrine()
->getRepository('Aleph2OmegaTranscriptionBundle:Lexeme')
->createQueryBuilder('l')
->orderBy('l.id', 'asc')
->setMaxResults(1)
->getQuery();
$nextLexeme = $query->getResult();
}
if ( count($previousLexeme) < 1 ) {
$query = $this->getDoctrine()
->getRepository('Aleph2OmegaTranscriptionBundle:Lexeme')
->createQueryBuilder('l')
->orderBy('l.id', 'desc')
->setMaxResults(1)
->getQuery();
$previousLexeme = $query->getResult();
}
if (!$lexeme) {
$lexeme = new Lexeme();
}
$form = $this->createForm(new EditLexemeType(), $lexeme);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($lexeme);
$em->flush();
return $this->redirect($this->generateUrl('aleph2_omega_transcription_lexemes_edit', array ('id'=>$lexeme->getId())));
}
return $this->render('Aleph2OmegaTranscriptionBundle:Lexeme:edit.html.twig', array(
'form' => $form->createView(),
'previousId' => $previousLexeme[0]->getId(),
'nextId' => $nextLexeme[0]->getId()
));
}
Lexeme表格类型:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$formModifier = function (FormInterface $form, $language) {
$form
->remove('phonemes')
->add('phonemes', 'entity', array(
'class' => 'Aleph2OmegaTranscriptionBundle:Phoneme',
'property' => 'latin',
'expanded' => true,
'multiple' => true,
'by_reference' => false,
'query_builder' => function(EntityRepository $er) use ($language) {
return $er->createQueryBuilder('u')
->select('p')
->from('Aleph2OmegaTranscriptionBundle:Phoneme', 'p')
->where('p.language = :language')
->setParameter('language', $language);
},
));
};
$builder
->add('language', 'entity', array(
'class' => 'Aleph2OmegaTranscriptionBundle:Language',
'property' => 'name',
'expanded' => false,
'multiple' => false,
))
->add('defaultGreek')
->add('defaultHebrew')
->add('save', 'submit')
//->add('id', 'hidden')
->add('words', 'collection', array(
'type' => new WordLimitedProtoType(),
'allow_add' => true,
'allow_delete' => true,
'options' => array('data_class' => 'Aleph2Omega\TranscriptionBundle\Entity\Word'),
'prototype' => true,
'by_reference' => false,
))
->add('phonemes', 'entity', array(
'class' => 'Aleph2OmegaTranscriptionBundle:Phoneme',
'property' => 'latin',
'expanded' => true,
'multiple' => true,
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->select('p')
->from('Aleph2OmegaTranscriptionBundle:Phoneme', 'p')
->where('p.language = :language')
->setParameter('language', '1');
},
))
->add('save', 'submit')
->setMethod('POST')
->addEventListener(
FormEvents::POST_SUBMIT,
function ($event) {
$event->stopPropagation();
},
900)
->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
if ($data instanceof Word) {
$formModifier($event->getForm(), $data->getLanguage());
}
}
)
->get('language')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$language = $event->getForm()->getData();
$formModifier($event->getForm()->getParent(), $language);
});
}
Lexeme Twig模板:
{{ include('Aleph2OmegaTranscriptionBundle::menu.html.twig') }}
{{ form_start(form) }}
{{ form_row(form._token) }}
<h1><a href="{{ path('aleph2_omega_transcription_lexemes_edit', {'id': previousId}) }}"><</a> Edit Lexeme <a href="{{ path('aleph2_omega_transcription_lexemes_edit', {'id': nextId}) }}">></a></h1>
{{ form_errors(form) }}
<table>
<tr><th>Language</th><td>{{ form_widget(form.language) }}</td></tr>
<tr><th>Default Greek</th><td>{{ form_widget(form.defaultGreek) }}</td></tr>
<tr><th>Default Hebrew</th><td>{{ form_widget(form.defaultHebrew) }}</td></tr>
</table>
<table>
<tr><th>Phonemes</th></tr>
<tr><td>{{ form_widget(form.phonemes) }}</td></tr>
</table>
<h3>{{ form_widget(form.save) }}</h3>
<table class="words" data-prototype="{% filter escape %}{% include 'Aleph2OmegaTranscriptionBundle:Word:limited_prototype.html.twig' with { 'item': form.words.vars.prototype } %}{% endfilter %}">
{# iterate over each existing word and render its fields #}
<tr><th>transcription</th><th>normalised</th><th>Hebrew</th><th>comment</th></tr>
{% for word in form.words %}
<tr>
<td>{{ form_widget(word.transcription) }}</td>
<td>{{ form_widget(word.normalisedTranscription) }}</td>
<td>{{ form_widget(word.hebrewTranscription) }}</td>
<td>{{ form_widget(word.comment) }}</td>
</tr>
{{ form_rest(word) }}
{% endfor %}
</table>
{{ form_rest(form) }}
{{ form_end(form) }}
AJAX的javascript:
jQuery(document).ready(function() {
$("[id$=language]").change(function() {
languageChange();
});
function languageChange() {
var $languages = $("[id$=language]");
$($languages).each(function() {
var $form = $(this).closest('form');
var data = {};
data[$(this).attr('name')] = $(this).val();
$.ajax({
url : $form.attr('action'), //Routing.generate('route_id', /* your params */), //
type: $form.attr('method'),
data: data,
success: function(html) {
$phonemes = $("[id$=phonemes]");
$($phonemes).each(function() {
$(this).replaceWith(
$(html).find('#'+this.id)
);
});
}
});
});
}
languageChange();
});
更新:一些屏幕截图
在私人通信中,有些人希望澄清我正在寻找的行为。
这是来自不同实体(单词)的页面,它没有使用AJAX来填充音素字段。这展示了我想要的那种行为:
通过AJAX更新的Lexeme实体(上面的代码用于)正确地显示了每种语言的正确音素,它只是将数据库中记录的音素标记为&#34;已连接&# 34;不检查Lexeme。
,例如,这是正确显示的音素,当希伯来语&#34;被选中:
以下是&#34;希腊语&#34;正确显示的音素。被选中:
最后,就调试而言,我已经扎根于使用Chrome控制台和网络显示器,这暗示问题可能是由于CSRF与AJAX有关。但是,我不明白的是 - 如果CSRF确实存在问题,为什么页面会从服务器返回?
更新2:部分解决方法
好的,所以至少要正确显示初始页面加载的部分解决方法是避免AJAX调用。这并没有解决确保AJAX更新正确显示所有内容的问题,但至少可以改进功能(我认为,这是一种比使用AJAX更好的预填充表单的方法)。
在buildForm函数中,可以使用以下命令获取填充表单的数据:
$lexemeEntity = $builder->getData();
然后可以将其输入到填充音素实体类型的初始查询中(注意,不要忘记&#34;使用&#34;这在定义函数的声明中):
'query_builder' => function(EntityRepository $er) use ($lexemeEntity) {
return $er->createQueryBuilder('u')
->select('p')
->from('Aleph2OmegaTranscriptionBundle:Phoneme', 'p')
->where('p.language = :language')
->setParameter('language', $lexemeEntity->getLanguage());
},
最后,需要在javascript中关闭每个页面初始加载的默认AJAX调用。我只是通过评论来做到这一点:
//languageChange();
现在初始页面加载都已正确填充 - 但是使用AJAX对表单的进一步更新仍然没有加载所有数据,对此仍然非常欢迎。