Symfony 3 - 动态表单 - ChoiceType Ajax

时间:2017-06-29 13:47:08

标签: php ajax forms symfony events

我目前正在处理用户创建表单。

用户具有个人资料属性:

    /**
     * Many Users have One profile
     * @ORM\ManyToOne(targetEntity="ProjectBundle\Entity\User\Profile", inversedBy="users")
     * @ORM\JoinColumn(name="profile_id", referencedColumnName="id")
     */
    private $profile;

根据另一个选择(在更改操作jquery上)选择此配置文件:

{% autoescape  'html'%}
        {{ '<script id="tmpl_user_profile" type="text/x-jquery-tmpl">
                <option value="${id}">${libelle}</option>
        </script>'|raw }}
{% endautoescape  %}

    <script>
        $('select#user_organisationMember').on('change',function(){
            var value = this.value;
            if (value == '') {
                $('#user_profile').empty();
            }
            var urlAjax = "{{ path('admin_user_get_profile', { 'entity': "value" }) }}";
            $.ajax({
                url: urlAjax.replace("value",value),
                method: "post"
            }).done(function(msg){
                $('#user_profile').empty();
                $('#tmpl_user_profile').tmpl(JSON.parse(msg)).appendTo('#user_profile');
            }) ;
        });
    </script>

在此之前一切正常! select标签中的不同配置文件会根据其他选择进行更改。

到达页面后,我希望个人资料列表为空。

所以我使用Symfony的FormEvent修改了我的表单。

这是我第一次使用FormEvent,我可能犯了一个错误!

我的FormType:

/**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('lastname')
            ->add('firstname')
            ->add('gender',null,array('required'=>true))
            ->add('organisationMember',null,array(
                'required' => true,
                'choices' => $options['organisation'],
                'group_by' => 'type_organisation',
                'placeholder' => 'Choisissez votre organisation'
            ))
            ->add('job')
            ->add('mobile')
            ->add('phone')
            ->add('alert_failure')
            ->add('alert_full')
            ->add('alert_other')
            ->add('plainPassword', TextType::class, array('required' => true))
            ->add('email')
            ->add('profile', null, array(
                'required' => true,
            ));

        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $entity = $event->getData();
            $form = $event->getForm();

            if (!$entity || null === $entity->getId()) {
                $form->remove('profile');
                $form->add('profile', ChoiceType::class);
            }
        });
    }

默认情况下,我的数据库的所有配置文件都会在选择中加载,以便不会出现错误&#39;此值不正确&#39;。

但我不希望用户看到所有个人资料,所以我在事件中将其删除并将该字段返回为空。

但我仍然收到错误&#39;此值不正确&#39;因为实际上,由于基本选择为空,表单未找到输入的值。

我想有一个默认为空的选项,它在Ajax中填充,但没有显示错误&#39;此值不正确&#39;。

我怎么能这样做? 谢谢

2 个答案:

答案 0 :(得分:0)

不仅在PRE_SET_DATA上添加字段,还在PRE_SUBMIT事件上添加字段。在类似问题上查看我的answer

答案 1 :(得分:0)

我找到了一个非常简单的解决方案,我不知道这是不是一个好主意,但它不需要很多行。

我已发送默认表单

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('lastname')
            ->add('firstname')
            ->add('gender',null,array('required'=>true))
            ->add('organisationMember',null,array(
                'required' => true,
                'choices' => $options['organisation'],
                'group_by' => 'type_organisation',
                'placeholder' => 'Choisissez votre organisation'
            ))
            ->add('job')
            ->add('mobile')
            ->add('phone')
            ->add('alert_failure')
            ->add('alert_full')
            ->add('alert_other')
            ->add('plainPassword', TextType::class, array('required' => true))
            ->add('email')
            ->add('profile', null, array(
                'required' => true,
                'placeholder' => 'Choose an organisation !',
            ));
    }

在我看来:

<div class="form-group{% if form.profile.vars.errors|length %} has-error{% endif %}">
        <label for="{{ form.profile.vars.id }}" class="col-sm-3 control-label no-padding-right required">Profile(s) </label>
        <div class="col-sm-9">
            {% do form.profile.setRendered %}
            <select name="user[profile]" id="user_profile" required class="form-control">
             //We can do a loop if needed
            </select>
            {{ form_errors(form.profile) }}
        </div>
</div>

通过这种方式,我可以完全管理是否需要选择信息。

它对我有用。