Symfony,如何使用表单事件来验证动态客户端表单 [英] Symfony, how to use form event to validate dynamic client-side form

查看:342
本文介绍了Symfony,如何使用表单事件来验证动态客户端表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用带有ajax的select2插件在我的表单上有一个动态字段,但是当我提交时,它返回一个错误该值无效,这是正常的原因我在选项 ChoiceType 和一个空的 array() c>创建选项。根据部分的symfony文档,表单事件是我的救星,所以试图使用它,但它看起来像我的代码有问题,并不能真正看到。



问题是:



如何将选择可能性传递给该字段,以使表单有效。

我的表单类型

  class ArticleType extends AbstractType 
{
/ **
* {@inheritdoc}
* /
public function buildForm(FormBuilderInterface $ builder,array $ options)
{
$ builder
//我的其他领域

//我的函数添加可能的选择字段
$ formModifier = function(FormInterface $ form,$ imageValue)use($ options){
if($ imageValue!== null){
$ listImages = $ this-> getChoiceValue($ imageValue,$ options);

if(!$ listImages){
$ form-> get('image') - > addError(new FormError(
'Nous n \''vons pas pu trouver l'''mage,veuiller choisir une autre'
));
}
} else {
$ listImages = array();
}

// die(var_dump($ listImages)); //数组

$ form-> add('image',ChoiceType :: class,array($ b $'attr'=> array(
'id' =>'image'),
'expanded'=> false,
'multiple'=> false,
'choices'=> $ listImages));
};
$ b $ formModifierSubmit = Form(FormInterface $ form,$ imageValue)use($ options){
if($ imageValue!== null){
$ listImages = $ this- > getChoiceValue($ imageValue,$ options);

if(!$ listImages){
$ form-> get('image') - > addError(new FormError(
'Nous n \''vons pas pu trouver l'''mage,veuiller choisir une autre'
));
}
} else {
$ form-> get('image') - > addError(new FormError(
'Veuillez choisir une image svp'
));
}

// die(var_dump($ listImages)); // Image对象数组

$ config = $ form-> get('image') - > getConfig();
$ opts = $ config-> getOptions();
$ chcs = array('choices'=> $ listImages);
// die(var_dump($ chcs)); //输出一个带有'options'键的数组
array_replace($ opts,$ chcs); //不工作
// array_merge($ opts,$ chcs); //不工作
// die(var_dump($ opts)); //替换/合并不成立
};

$ builder-> addEventListener(
FormEvents :: PRE_SET_DATA,
function(FormEvent $ event)use($ formModifier){
// this will be the实体Article
$ data = $ event-> getData();

$ formModifier($ event-> getForm(),$ data-> getImage());
}
);
$ b $ // builder-> get('image') - > addEventListener(//提供错误导致字段图像不存在
$ builder-> addEventListener(
FormEvents :: PRE_SUBMIT,
function(FormEvent $ event)use($ formModifierSubmit){
$ imageVal = $ event-> getData();
// die(var_dump( $ imageVal)); //返回数组中的所有提交的数据字段
//但是,当将此事件更改为Submit时,将返回由提交的数据填充的Article模型,除了值为$的null图像字段b
$ b $ formModifierSubmit($ event-> getForm(),$ imageVal ['image']);
}
);
}

public function getChoiceValue($ imageValue,$ options)
{
$ listImages = $ options ['em'] - > getRepository('AlmotivAppBundle:Image') - > findBy(array(
'id'=> $ imageValue
));

return $ listImages; // Image对象数组
}
[...]
}

信息



我的图片字段不依赖于任何其他因为我需要在 PRE_SUBMIT 事件上填充选项选项以给出可能的选择。 / p>

并且 image 在我的 Article中有一个ManyToOne关系实体

  class Article实现HighlightableModelInterface 
{
//一些属性
/ **
* @ ORM \ManyToOne(targetEntity =Image \Entity\Path,cascade = {persist})
* @ Assert \Valid()
* /
private $ image;
}

如果我处于不良状态,请告诉我因为我离开的想法现在,我尝试了很多东西,比如


  • array_replace与字段配置中的选项相关,但没有错误。

  • 向表单操作 url:$ form.attr('action')的url发送ajax请求,我认为它会加载选项选项可能包含< option> 但我的选择依然返回无< option>



以及更多(不能remmenber)。



此外,我还在使用select2插件的v4.0.3框架的v3.1,如果需要更多的信息,只需要询问和thx阅读和尝试帮助。 p>

编辑

只需添加一些信息即可更清楚

$ b

解决方案

你让事情太复杂。在您的文档示例中,他们为已经存在的表单字段('sport')添加eventListener,并将其添加到稍后添加的不存在的字段(文档示例中的'image'字段和'position'字段) p>

您应该使用 EntityType ,如果你需要(我不确定你是谁)用 query_builder 选项,用于验证添加约束条件

  class ArticleType extends AbstractType {
/ **
* {@inheri tdoc}
* /
public function buildForm(FormBuilderInterface $ builder,array $ options)
{

// $ builder
// My other field
$ imageFieldFunction = $ this-> getImageFieldFunction();

$ builder-> addEventListener(FormEvents :: PRE_SET_DATA,$ imageFieldFunction);
$ builder-> addEventListener(FormEvents :: PRE_SUBMIT,$ imageFieldFunction);

$ b private function getImageFieldFunction()
{
return function(FormEvent $ event){
$ form = $ event-> getForm() ;
$ data = $ event-> getData();
//当你的data_class是Article
$ image = $ data-> getImage(); //取决于你的Article类
/ *如果你正在使用data_class => null
$ image = $ data ['image'];
* /
$ imageId = $ image? $ image-> getId():0;

uilder-> add('image',EntityType :: class,array(
'class'=>'AlmotivAppBundle:Image',
'attr'= > array(
'id'=>'image'
),
'expanded'=> false,
'multiple'=> false,
'constraints'=> new NotBlank(),
'query_builder'=> function(EntityRepository $ er)use($ imageId){
return $ er-> createQueryBuilder('i')
- > where('i.id =:image_id')
- > setParameter('image_id',$ imageId);
}

)) ;
}
}
}


I'm using the select2 plugin with ajax to have a dynamic field on my form, but when i submit the it return me an error "This value is not valid", which is normal cause i use the ChoiceType with an empty array() in the choices options on creation. According to this part of the symfony doc, the form event is my savior, so trying to use it but it look like something wrong with my code and can't really see what.

So My Question Is :

HOW to pass the choices possibility to the field, for the form to be valid.

My form Type

class ArticleType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            //My other field

        //My functions to add the field with the possible choices
        $formModifier = function (FormInterface $form, $imageValue) use ($options) {
            if ($imageValue !== null) {
                $listImages = $this->getChoiceValue($imageValue, $options);

                if (!$listImages) {
                    $form->get('image')->addError(new FormError(
                    'Nous n\'avons pas pu trouver l\'image, veuiller choisir une autre'
                    ));
                }
            } else {
                $listImages = array();
            }

            //die(var_dump($listImages)); //Array of Image

            $form->add('image', ChoiceType::class, array(
                'attr' => array(
                    'id' => 'image'),
                'expanded' => false,
                'multiple' => false,
                'choices' => $listImages));
        };

        $formModifierSubmit = function (FormInterface $form, $imageValue) use ($options) {
            if ($imageValue !== null) {
                $listImages = $this->getChoiceValue($imageValue, $options);

                if (!$listImages) {
                    $form->get('image')->addError(new FormError(
                        'Nous n\'avons pas pu trouver l\'image, veuiller choisir une autre'
                    ));
                }
            } else {
                $form->get('image')->addError(new FormError(
                    'Veuillez choisir une image s.v.p.'
                ));
            }

            //die(var_dump($listImages)); //Array of Image object

            $config = $form->get('image')->getConfig();
            $opts = $config->getOptions();
            $chcs = array('choices' => $listImages);
            //die(var_dump($chcs)); //output an array with a 'choices' keys with array value
            array_replace($opts, $chcs); //not work
            //array_merge($opts, $chcs); //not work
            //die(var_dump($opts)); //replacements/merge are not made
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {
                // this would be the entity Article
                $data = $event->getData();

                $formModifier($event->getForm(), $data->getImage());
            }
        );

        //$builder->get('image')->addEventListener( //give error cause the field image don't exist
        $builder->addEventListener(
            FormEvents::PRE_SUBMIT,
            function (FormEvent $event) use ($formModifierSubmit) {
                $imageVal = $event->getData();
                //die(var_dump($imageVal)); //return all the submitted data field in an array
                //But when change this event to Submit it return the Article model populated by the submitted data, EXCEPT the image field which have null as value

                $formModifierSubmit($event->getForm(), $imageVal['image']);
            }
        );
    }

    public function getChoiceValue($imageValue, $options)
    {
        $listImages = $options['em']->getRepository('AlmotivAppBundle:Image')->findBy(array(
            'id' => $imageValue
        ));

        return $listImages; //array of Image object
    }
    [...]
}

For Info

My image field is not depending on any other field like the doc example, so i need to populate the choices options on PRE_SUBMIT event to give the possible choice.

And also image have a ManyToOne relation in my Article entity

class Article implements HighlightableModelInterface
{
    //some properties
    /**
     * @ORM\ManyToOne(targetEntity="Image\Entity\Path", cascade={"persist"})
     * @Assert\Valid()
     */
    private $image;
}

If i'm in the bad way let me know cause i'm out of idea now, i try much thing, like

  • array_replace with the options in the configuration of the field but didn't wrong.
  • make an ajax request to the url of the form action url : $form.attr('action'), i think it will load the choices option with the possible of <option> but my select is still returned with none <option>.

and much more (can't remmenber).

And also i'm using the v3.1 of the framework with the v4.0.3 of the select2 plugin, if need more info just ask and thx for reading and trying help.

Edit

Just add some info to be more clear

解决方案

You making things way too complicated. In your documentation example they add eventListener for already existing form field ('sport') and you are adding it to only later added field which does not exist (your 'image' field and 'position' field from the documentation example).

You should use EntityType and if you need (which I'm not if sure you are) filter your images using query_builder option, for validation add constraints (example with controller).

class ArticleType extends AbstractType {
/**
 * {@inheritdoc}
 */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

         // $builder
         // My other field
         $imageFieldFunction = $this->getImageFieldFunction();

         $builder->addEventListener(FormEvents::PRE_SET_DATA, $imageFieldFunction);
         $builder->addEventListener(FormEvents::PRE_SUBMIT, $imageFieldFunction);

    }
    private function getImageFieldFunction()
    {
         return function(FormEvent $event) {
             $form = $event->getForm();
             $data = $event->getData();
             //when your data_class is Article 
             $image = $data->getImage();//depending on your Article class
             /*if you are using data_class => null
             $image = $data['image'];
              */
             $imageId = $image ? $image->getId() : 0;

             $builder->add('image', EntityType::class , array(
            'class' => 'AlmotivAppBundle:Image',
             'attr' => array(
                'id' => 'image'
             ) ,
             'expanded' => false,
             'multiple' => false,
             'constraints' => new NotBlank(),
             'query_builder' => function (EntityRepository $er) use ($imageId) {
                  return $er->createQueryBuilder('i')
                            ->where('i.id = :image_id')
                            ->setParameter('image_id', $imageId);
             }

         ));
         }
    }
}

这篇关于Symfony,如何使用表单事件来验证动态客户端表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆