繁体   English   中英

以动态形式Symfony2填充实体字段类型

[英]Populating entity field type in dynamic form Symfony2

我有一个实体Lexeme,其中包含语言和音素实体。

在我的表单类型中,我希望根据为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}) }}">&#60;</a> Edit Lexeme <a href="{{ path('aleph2_omega_transcription_lexemes_edit', {'id': nextId}) }}">&#62;</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的其他实体,显示所需的行为

通过AJAX更新的Lexeme实体(上面的代码所针对的)正确显示了每种语言的正确音素,只是没有检查数据库中记录为“已连接”到Lexeme的音素。

例如,当选择“希伯来语”时,以下是正确显示的音素:

显示希伯来音素的依赖AJAX的Lexeme实体的部分正确行为

以下是选择“希腊语”时正确显示的音素:

显示希腊音素的依赖AJAX的Lexeme实体的部分正确行为

最后,就调试而言,我已经扎根使用Chrome控制台和网络显示,这表明问题可能是由于CSRF和AJAX引起的。 但是,我不明白的是-如果CSRF确实是问题所在,为什么从服务器返回页面呢?

尝试进行调试:Chrome与服务器的网络通信中的CSRF问题-相关?

更新2:部分解决方法

好的,因此至少可以正确显示初始页面加载的部分解决方法是避免AJAX调用。 这不能解决确保AJAX更新正确显示所有内容的问题,但至少可以改善功能(并且,我认为,与使用AJAX相比,预填充表单是一种更好的做法)。

在buildForm函数中,可以使用以下方法获取填充表单的数据:

$lexemeEntity = $builder->getData();

然后可以将其输入填充音素实体类型的初始查询中(请注意,不要忘记在定义的函数的声明中“使用”此字形):

    '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对表单进行的进一步更新仍未加载所有数据,对此仍然有任何帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM