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

时间:2014-11-29 04:41:06

标签: javascript php ajax forms symfony

我有一个实体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}) }}">&#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来填充音素字段。这展示了我想要的那种行为: A different entity that doesn't rely on AJAX, displaying the desired behaviour

通过AJAX更新的Lexeme实体(上面的代码用于)正确地显示了每种语言的正确音素,它只是将数据库中记录的音素标记为&#34;已连接&# 34;不检查Lexeme。

,例如,这是正确显示的音素,当希伯来语&#34;被选中:

Partially correct behaviour of the AJAX dependent Lexeme entity displaying Hebrew phonemes

以下是&#34;希腊语&#34;正确显示的音素。被选中:

Partially correct behaviour of the AJAX dependent Lexeme entity displaying Greek phonemes

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

An attempt to debug: a CSRF problem in Chrome's Network communication with the server—relevant??

更新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对表单的进一步更新仍然没有加载所有数据,对此仍然非常欢迎。

0 个答案:

没有答案