添加事件侦听器以形成由事件侦听器添加的元素 [英] Add event listener to form element added by event listener

查看:219
本文介绍了添加事件侦听器以形成由事件侦听器添加的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个Symfony应用程序,并使用一些jquery / ajax的表单事件来完成整个状态/局部的事情。我有一个小问题,但我使用格式省 - >城市 - >郊区。现在我可以告诉我的代码是正常的,但是当执行命中我添加一个监听器到城市选择的部分,它会抛出一个错误,说出如下:



名称为physicalCity的小孩不存在。



并向新创建的字段添加事件监听器,从而将事件侦听器添加到由事件侦听器创建的元素?



代码的一部分在下面...我做错了什么?任何帮助将非常感谢!

  public function buildForm(FormBuilderInterface $ builder,array $ options){
$构建器
- > add('schoolName')
- > add('physicalProvince','entity',array(
'mapped'=> false,
' class'=>'MY\MainBundle\Entity\Province',
'empty_value'=>'选择省',
'attr'=>数组(
'class'=>'省',
'data-show'=>'physical-city',

));

/ *
*对于物理城市
* /
$ physicalCityModifier = function(FormInterface $ form,Province $ province = null){
if (null!== $ province)
$ cities = $ province-> getCities();
else
$ cities = array();

$ form-> add('physicalCity','entity',array(
'mapped'=> false,
'class'=>'MY\\ \\ MainBundle\Entity\City',
'empty_value'=>'选择省份',
'choices'=> $ cities,
'attr'=>数组(
'class'=>'city physical-city',
'data-show'=>'physical -urban'

));
};

$ builder-> addEventListener(
FormEvents :: PRE_SET_DATA,
函数(FormEvent $ event)use($ physicalCityModifier){
$ data = $ event- > getData();
if(is_object($ data-> getPhysicalSuburb()))
$ province = $ data-> getPhysicalSuburb() - > getCity() - > getProvince );
else
$ province = null;

$ physicalCityModifier($ event-> getForm(),$ province);
}
) ;

$ builder-> get('physicalProvince') - > addEventListener(
FormEvents :: POST_SUBMIT,
函数(FormEvent $ event)use($ physicalCityModifier){
$ province = $ event-> getForm() - > getData();
$ physicalCityModifier($ event-> getForm() - > getParent(),$ province);
}
);

/ *
*对于实体郊区
* /
$ physicalSuburbModifier = function(FormInterface $ form,City $ city = null){
if (null!== $ city)
$ streetss = $ city-> getSuburbs();
else
$ streetss = array();

$ form-> add('physicalSuburb',null,array(
'choices'=> $郊区,
'empty_value'=>'选择一个城市第一个',
'attr'=>数组(
'class'=>'物理郊区'
),
));
};

$ builder-> addEventListener(
FormEvents :: PRE_SET_DATA,
函数(FormEvent $ event)use($ physicalSuburbModifier){
$ data = $ event- > getData();
if(is_object($ data-> getCity()))
$ city = $ data-> getCity();
else
$ city = null;

$ physicalSuburbModifier($ event-> getForm(),$ city);
}
);

$ builder-> get('physicalCity') - > addEventListener(
FormEvents :: POST_SUBMIT,
函数(FormEvent $ event)use($ physicalSuburbModifier){
$ city = $ event-> getForm() - > getData();

$ physicalSuburbModifier($ event-> getForm() - > getParent(),$ city) ;
}
);
}


解决方案

如果有人有类似的问题,我终于得到了正确的事件订阅者每个领域,在这个网站(为我们之间的非西班牙语民歌翻译)。



我所做的是为每个字段创建一个新的Subscriber类,包括省,和然后在其中每个中创建一个查询构建器,以便将它们的值与前面的字段填充。代码如下所示。



AddProvinceFieldSubscriber.php

  class AddProvinceFieldSubscriber实现EventSubscriberInterface {
私人$工厂;
private $ fieldName;
private $ type;

public function __construct(FormFactoryInterface $ factory,$ fieldName){
$ this-> factory = $ factory;
$ this-> fieldName = $ fieldName。 '省';
$ this-> type = $ fieldName;
}

public static function getSubscribedEvents(){
return array(
FormEvents :: PRE_SET_DATA =>'preSetData',
FormEvents :: PRE_SUBMIT ='preSubmit',
);
}

私有函数addProvinceForm(FormInterface $ form,$ province){
$ form-> add($ this-> factory-> createNamed($ this- > fieldName,'e​​ntity',$ province,array(
'class'=>'MyThing\MainBundle\Entity\Province',
'mapped'=> false,
'empty_value'=>'选择省',
'query_builder'=> function(EntityRepository $ repository){
$ qb = $ repository-> createQueryBuilder('p');
return $ qb;
},
'auto_initialize'=> false,
'attr'=>数组(
'class'=>'省'。$ this-> type .'- province',
'data-show'=> $ this-> type。'-city',

))) ;
}

public function preSetData(FormEvent $ event){
$ form = $ event-> getForm();
$ data = $ event-> getData();

if(null === $ data)
return;

$ fieldName ='get'。 ucwords($ this-> type)。 '市郊';
$ province =($ data-> $ fieldName())? $ data-> $ fieldName() - > getCity() - > getProvince():null;
$ this-> addProvinceForm($ form,$ province);
}

public function preSubmit(FormEvent $ event){
$ form = $ event-> getForm();
$ data = $ event-> getData();

if(null === $ data)
return;

$ province = array_key_exists($ this-> fieldName,$ data)? $ data [$ this-> fieldName]:null;
$ this-> addProvinceForm($ form,$ province);
}
}

AddCityFieldSubscriber.php

  class AddCityFieldSubscriber实现EventSubscriberInterface {
private $ factory;
private $ fieldName;
private $ provinceName;
private $ streetsName;
private $ type;

public function __construct(FormFactoryInterface $ factory,$ fieldName){
$ this-> factory = $ factory;
$ this-> fieldName = $ fieldName。 '市';
$ this-> provinceName = $ fieldName。 '省';
$ this-> ;urbanName = $ fieldName。 '市郊';
$ this-> type = $ fieldName;
}

public static function getSubscribedEvents(){
return array(
FormEvents :: PRE_SET_DATA =>'preSetData',
FormEvents :: PRE_SUBMIT ='preSubmit',
);
}

private function addCityForm(FormInterface $ form,$ city,$ province){
$ form-> add($ this-> factory-> createNamed $ this-> fieldName,'e​​ntity',$ city,array(
'class'=>'MyThing\MainBundle\Entity\City',
'empty_value'=>'选择城市',
'映射'=> false,
'query_builder'=> function(EntityRepository $ repository)use($ province){
$ qb = $ repository-> ; createQueryBuilder('c')
- > innerJoin('c.province','province');
if($ province instanceof Province){
$ qb-> where( 'c.province =:province')
- > setParameter('province',$ province);
} elseif(is_numeric($ province)){
$ qb-> where ('province.id =:province')
- > setParameter('province',$ province);
} else {
$ qb-> where('province.provinceName =:province')
- > setParameter省,null);
}

return $ qb;
},
'auto_initialize'=> false,
'attr'=>数组(
'class'=>'city'。$ this-> type。'-city',
'data-show'=> $ this-> type。'-suburb ',

)));
}

public function preSetData(FormEvent $ event){
$ data = $ event-> getData();
$ form = $ event-> getForm();

if(null === $ data){
return;
}

$ fieldName ='get'。 ucwords($这 - > suburbName);
$ city =($ data-> $ fieldName())? $ data-> $ fieldName() - > getCity():null;
$ province =($ city)? $ city-> getProvince():null;
$ this-> addCityForm($ form,$ city,$ province);
}

public function preSubmit(FormEvent $ event){
$ data = $ event-> getData();
$ form = $ event-> getForm();

if(null === $ data)
return;

$ city = array_key_exists($ this-> fieldName,$ data)? $ data [$ this-> fieldName]:null;
$ province = array_key_exists($ this-> provinceName,$ data)? $ data [$ this-> provinceName]:null;
$ this-> addCityForm($ form,$ city,$ province);
}
}

最后AddSuburbFieldSubscriber.php

  class AddSuburbFieldSubscriber实现EventSubscriberInterface {
private $ factory;
private $ fieldName;
private $ type;

public function __construct(FormFactoryInterface $ factory,$ fieldName){
$ this-> factory = $ factory;
$ this-> fieldName = $ fieldName。 '市郊';
$ this-> type = $ fieldName;
}

public static function getSubscribedEvents(){
return array(
FormEvents :: PRE_SET_DATA =>'preSetData',
FormEvents :: PRE_SUBMIT ='preSubmit',
);
}

私有函数addSuburbForm(FormInterface $ form,$ city){
$ form-> add($ this-> factory-> createNamed($ this- > fieldName,'e​​ntity',null,array(
'class'=>'MyThing\MainBundle\Entity\Suburb',
'empty_value'=>'选择郊区' ,
'query_builder'=> function(EntityRepository $ repository)use($ city){
$ qb = $ repository-> createQueryBuilder('s')
- > innerJoin 's.city','city');

if($ city instanceof City){
$ qb-> where('s.city =:city')
- > setParameter('city',$ city);
} elseif(is_numeric($ city)){
$ qb-> where('city.id =:city')
- > setParameter('city',$ city);
} else {
$ qb-> where('city.cityName =:city')
- > setParameter('city',null);
}
$ sql = $ qb-> getQuery() - > getSQL();

return $ qb;
},
'auto_initialize'=> false,
'attr'=>数组(
'class'=>'郊区'$ this-> type。'-suburb',
),
)));
}

public function preSetData(FormEvent $ event){
$ data = $ event-> getData();
$ form = $ event-> getForm();

if(null === $ data)
return;

$ fieldName ='get'。 ucwords($这 - > fieldName的);
$ city =($ data-> $ fieldName())? $ data-> $ fieldName() - > getCity():null;
$ this-> addSuburbForm($ form,$ city);
}

public function preSubmit(FormEvent $ event){
$ data = $ event-> getData();
$ form = $ event-> getForm();

if(null === $ data)
return;

$ city = array_key_exists($ this-> type。'City',$ data)? $ data [$ this-> type。 'City']:null;
$ this-> addSuburbForm($ form,$ city);
}
}

我不得不在那里添加一些额外的东西,但是你得到它的要点。



在我的表单类型中,我只是添加了以下内容:

  $ builder 
- > addEventSubscriber(new AddProvinceFieldSubscriber($ factory,'postal'))
- > addEventSubscriber(new AddCityFieldSubscriber($ factory,'postal'))
- > addEventSubscriber新的AddSuburbFieldSubscriber($ factory,'postal'))
// ...

快乐的时光!希望这有助于某人。



此外,我添加了 data-show 属性,以简化我的AJAX过程,以防有人在想。


I'm building a Symfony app and using form events with some jquery/ajax to do the whole "state/locality" thing. I have a slight issue though, I am using the format Province -> City -> Suburb. Now as far as I can tell my code is fine, but when the execution hits the section where I add a listener to the "City" select, it throws an error saying the following:

The child with the name "physicalCity" does not exist.

This obviously happens when I try and add an event listener to the newly created field, thus adding an event listener to an element created by an event listener?

A section of the code is below... What am I doing wrong? Any help would be very much appreciated!

public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('schoolName')
            ->add('physicalProvince', 'entity', array(
                'mapped' => false,
                'class' => 'MY\MainBundle\Entity\Province',
                'empty_value' => 'Select a province',
                'attr' => array(
                    'class' => 'province',
                    'data-show' => 'physical-city',
                )
            ));

        /*
         * For the physical cities
         */
        $physicalCityModifier = function(FormInterface $form, Province $province = null) {
            if (null !== $province)
                $cities = $province->getCities();
            else
                $cities = array();

            $form->add('physicalCity', 'entity', array(
                'mapped' => false,
                'class' => 'MY\MainBundle\Entity\City',
                'empty_value' => 'Select a province first',
                'choices' => $cities,
                'attr' => array(
                    'class' => 'city physical-city',
                    'data-show' => 'physical-suburb'
                )
            ));
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function(FormEvent $event) use ($physicalCityModifier) {
                $data = $event->getData();
                if (is_object($data->getPhysicalSuburb()))
                    $province = $data->getPhysicalSuburb()->getCity()->getProvince();
                else
                    $province = null;

                $physicalCityModifier($event->getForm(), $province);
            }
        );

        $builder->get('physicalProvince')->addEventListener(
            FormEvents::POST_SUBMIT,
            function (FormEvent $event) use ($physicalCityModifier) {
                $province = $event->getForm()->getData();
                $physicalCityModifier($event->getForm()->getParent(), $province);
            }
        );

        /*
         * For the physical suburbs
         */
        $physicalSuburbModifier = function(FormInterface $form, City $city = null) {
            if (null !== $city)
                $suburbs = $city->getSuburbs();
            else
                $suburbs = array();

            $form->add('physicalSuburb', null, array(
                'choices' => $suburbs,
                'empty_value' => 'Select a city first',
                'attr' => array(
                    'class' => 'physical-suburb'
                ),
            ));
        };

        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function(FormEvent $event) use ($physicalSuburbModifier) {
                $data = $event->getData();
                if (is_object($data->getCity()))
                    $city = $data->getCity();
                else
                    $city = null;

                $physicalSuburbModifier($event->getForm(), $city);
            }
        );

        $builder->get('physicalCity')->addEventListener(
            FormEvents::POST_SUBMIT,
            function(FormEvent $event) use ($physicalSuburbModifier) {
                $city = $event->getForm()->getData();

                $physicalSuburbModifier($event->getForm()->getParent(), $city);
            }
        );
}

解决方案

If anybody else has a similar issue, I eventually got it right with event subscribers for each field, with help from this site (translate it for those non-spanish speaking folk among us).

Bascially, what I did was create a new Subscriber class for each field, including province, and then just created a query builder inside each of them to populate their values with those from the preceding fields. The code is shown below.

AddProvinceFieldSubscriber.php

class AddProvinceFieldSubscriber implements EventSubscriberInterface {
    private $factory;
    private $fieldName;
    private $type;

    public function __construct(FormFactoryInterface $factory, $fieldName) {
        $this->factory = $factory;
        $this->fieldName = $fieldName . 'Province';
        $this->type = $fieldName;
    }

    public static function getSubscribedEvents() {
        return array(
            FormEvents::PRE_SET_DATA => 'preSetData',
            FormEvents::PRE_SUBMIT => 'preSubmit',
        );
    }

    private function addProvinceForm(FormInterface $form, $province) {
        $form->add($this->factory->createNamed($this->fieldName, 'entity', $province, array(
            'class' => 'MyThing\MainBundle\Entity\Province',
            'mapped' => false,
            'empty_value' => 'Select a province',
            'query_builder' => function (EntityRepository $repository) {
                $qb = $repository->createQueryBuilder('p');
                return $qb;
            },
            'auto_initialize' => false,
            'attr' => array(
                'class' => 'province ' . $this->type .'-province',
                'data-show' => $this->type . '-city',
            )
        )));
    }

    public function preSetData(FormEvent $event) {
        $form = $event->getForm();
        $data = $event->getData();

        if (null === $data)
            return;

        $fieldName = 'get' . ucwords($this->type) . 'Suburb';
        $province = ($data->$fieldName()) ? $data->$fieldName()->getCity()->getProvince() : null;
        $this->addProvinceForm($form, $province);
    }

    public function preSubmit(FormEvent $event) {
        $form = $event->getForm();
        $data = $event->getData();

        if (null === $data)
            return;

        $province = array_key_exists($this->fieldName, $data) ? $data[$this->fieldName] : null;
        $this->addProvinceForm($form, $province);
    }
}

AddCityFieldSubscriber.php

class AddCityFieldSubscriber implements EventSubscriberInterface {
    private $factory;
    private $fieldName;
    private $provinceName;
    private $suburbName;
    private $type;

    public function __construct(FormFactoryInterface $factory, $fieldName) {
        $this->factory = $factory;
        $this->fieldName = $fieldName . 'City';
        $this->provinceName = $fieldName . 'Province';
        $this->suburbName = $fieldName . 'Suburb';
        $this->type = $fieldName;
    }

    public static function getSubscribedEvents() {
        return array(
            FormEvents::PRE_SET_DATA => 'preSetData',
            FormEvents::PRE_SUBMIT => 'preSubmit',
        );
    }

    private function addCityForm(FormInterface $form, $city, $province) {
        $form->add($this->factory->createNamed($this->fieldName, 'entity', $city, array(
            'class' => 'MyThing\MainBundle\Entity\City',
            'empty_value' => 'Select a city',
            'mapped' => false,
            'query_builder' => function (EntityRepository $repository) use ($province) {
                $qb = $repository->createQueryBuilder('c')
                                ->innerJoin('c.province', 'province');
                if ($province instanceof Province) {
                    $qb->where('c.province = :province')
                       ->setParameter('province', $province);
                } elseif (is_numeric($province)) {
                    $qb->where('province.id = :province')
                       ->setParameter('province', $province);
                } else {
                    $qb->where('province.provinceName = :province')
                       ->setParameter('province', null);
                }

                return $qb;
            },
            'auto_initialize' => false,
            'attr' => array(
                'class' => 'city ' . $this->type . '-city',
                'data-show' => $this->type . '-suburb',
            )
        )));
    }

    public function preSetData(FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();

        if (null === $data) {
            return;
        }

        $fieldName = 'get' . ucwords($this->suburbName);
        $city = ($data->$fieldName()) ? $data->$fieldName()->getCity() : null;
        $province = ($city) ? $city->getProvince() : null;
        $this->addCityForm($form, $city, $province);
    }

    public function preSubmit(FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();

        if (null === $data)
            return;

        $city = array_key_exists($this->fieldName, $data) ? $data[$this->fieldName] : null;
        $province = array_key_exists($this->provinceName, $data) ? $data[$this->provinceName] : null;
        $this->addCityForm($form, $city, $province);
    }
}

And finally AddSuburbFieldSubscriber.php

class AddSuburbFieldSubscriber implements EventSubscriberInterface {
    private $factory;
    private $fieldName;
    private $type;

    public function __construct(FormFactoryInterface $factory, $fieldName) {
        $this->factory = $factory;
        $this->fieldName = $fieldName . 'Suburb';
        $this->type = $fieldName;
    }

    public static function getSubscribedEvents() {
        return array(
            FormEvents::PRE_SET_DATA => 'preSetData',
            FormEvents::PRE_SUBMIT => 'preSubmit',
        );
    }

    private function addSuburbForm(FormInterface $form, $city) {
        $form->add($this->factory->createNamed($this->fieldName, 'entity', null, array(
            'class' => 'MyThing\MainBundle\Entity\Suburb',
            'empty_value' => 'Select a suburb',
            'query_builder' => function (EntityRepository $repository) use ($city) {
                $qb = $repository->createQueryBuilder('s')
                                ->innerJoin('s.city', 'city');

                if ($city instanceof City) {
                    $qb->where('s.city = :city')
                       ->setParameter('city', $city);
                } elseif (is_numeric($city)) {
                    $qb->where('city.id = :city')
                       ->setParameter('city', $city);
                } else {
                    $qb->where('city.cityName = :city')
                       ->setParameter('city', null);
                }
                    $sql = $qb->getQuery()->getSQL();

                return $qb;
            },
            'auto_initialize' => false,
            'attr' => array(
                'class' => 'suburb ' . $this->type . '-suburb',
            ),
        )));
    }

    public function preSetData(FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();

        if (null === $data)
            return;

        $fieldName = 'get' . ucwords($this->fieldName);
        $city = ($data->$fieldName()) ? $data->$fieldName()->getCity() : null;
        $this->addSuburbForm($form, $city);
    }

    public function preSubmit(FormEvent $event) {
        $data = $event->getData();
        $form = $event->getForm();

        if (null === $data)
            return;

        $city = array_key_exists($this->type . 'City', $data) ? $data[$this->type . 'City'] : null;
        $this->addSuburbForm($form, $city);
    }
}

I had to add some extra stuff in there, but you get the gist of it.

In my form type I simply added the following:

$builder
    ->addEventSubscriber(new AddProvinceFieldSubscriber($factory, 'postal'))
    ->addEventSubscriber(new AddCityFieldSubscriber($factory, 'postal'))
    ->addEventSubscriber(new AddSuburbFieldSubscriber($factory, 'postal'))
//...

And happy days! Hope this helps somebody.

Also, I added the data-show attributes to simplify my AJAX process, just in case somebody was wondering.

这篇关于添加事件侦听器以形成由事件侦听器添加的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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