Symfony5 使用 AJAX 表单多选(选择列表)数据自动更新

2024-01-10

我有一个位置表单,其中包含三个“选择”(选择列表):国家、地区和部门。这些“选择”默认包含所有国家、地区和部门的列表。我想让我的用户首先选择一个国家或地区或部门。

我想做的事:
当用户选择一个国家时,区域中的数据会根据该国家/地区而变化。地区和部门之间相同。

我拥有的:

  • 当我选择的时候先是一个国家,然后是一个地区,数据在国家和地区之间自动更新但对于区域到部门,AJAX请求不会启动.
  • 但如果我选择直接一个区域 then AJAX请求已启动,但未更新部门中的数据.
  • 但是,在表单中,当我评论有关国家和地区自动更新的部分时,AJAX 请求启动,区域和部门之间的自动更新工作。

这是我的表格:

//src/Form/LocationType.php
class LocationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('country', EntityType::class, [
        'class' => Country::class,
            ])
            ->add('area', EntityType::class, [
                'class' => Area::class,
                'required' => false
            ])
            ->add('department', EntityType::class, [
                'class' => Department::class,
                'required' => false
            ]);
            
        //The part I comment for makes the auto-update between area and department works
        $formArea = function(FormInterFace $form, Country $country = null) {
            if($country === null) {
                $form->add('area', EntityType::class, [
                    'class' => Area::class,
                    'required' => false
                ]);
            }
            else {
                $areas = $country->getAreas();
                $form->add('area', EntityType::class, [
                    'class' => Area::class,
                    'choices' => $areas,
                    'required' => false
                ]);
            }
        };

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

        $formDepartment = function(FormInterFace $form, Area $area = null) {
            if($area === null) {
                $form->add('department', EntityType::class, [
                    'class' => Department::class,
                    'required' => false
                ]);
            }
            else {
                $departments = $area->getDepartments();
                $form->add('department', EntityType::class, [
                    'class' => Department::class,
                    'choices' => $departments,
                    'required' => false
                ]);
            }
        };

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

以及AJAX调用的JS代码:

//assets/js/selectCountryAreaDepartment.js
window.onload = () => {
    let country = document.querySelector("#location_country");

    country.addEventListener("change", function() {
        let form = this.closest("form");
        let data = this.name + "=" + this.value;
        console.log(data);
        fetch(form.action, {
            method: form.getAttribute("method"),
            body: data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded; charset:UTF-8"
            }
        })
        .then(response => response.text())
        .then(html => {
            let content = document.createElement("html");
            content.innerHTML = html;
            let area = content.querySelector("#location_area");
            document.querySelector("#location_area").replaceWith(area);
            console.log(area);

        })
        .catch(error => {
            console.log(error);
        })
    });

    let area = document.querySelector("#location_area");

    area.addEventListener("change", function() {
        let formArea = this.closest("form");
        let dataArea = this.name + "=" + this.value;
        //console.log(formArea);
        console.log(dataArea);
        fetch(formArea.action, {
            method: formArea.getAttribute("method"),
            body: dataArea,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded; charset:UTF-8"
            }
        })
        .then(response => response.text())
        .then(html => {
            let contentArea = document.createElement("html");
            contentArea.innerHTML = html;
            let department = contentArea.querySelector("#location_department");
            document.querySelector("#location_department").replaceWith(department);
            console.log(department);
        })
        .catch(error => {
            console.log(error);
        })
    });

}

该代码基于此法语教程:https://www.youtube.com/watch?v=f7tdb30evUk https://www.youtube.com/watch?v=f7tdb30evUk


通过删除add()在 null 情况下表单修饰符 formArea and 表格部门当使用其他选择时,它避免“重置”选择:

//src/Form/LocationType.php
// …
        // formModifier
        $formArea = function(FormInterFace $form, LocationCountry $country = null) {
            if($country != null)
            {
                $areas = $country->getAreas();
            $form->add('area', EntityType::class, [
                'class' => LocationArea::class,
                'choices' => $areas,
                'placeholder' => 'select now an area',
                'required' => false
            ]);
            }
        };

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

        // formModifier
        $formDepartment = function(FormInterFace $form, LocationArea $area = null) {
            if($area != null) 
            {
                $departments = $area->getDepartments();
            $form->add('department', EntityType::class, [
                'class' => LocationDepartment::class,
                'choices' => $departments,
                'placeholder' => 'select now a department',
                'required' => false,
                'choice_label' => function ($departments) {
                    return '['.$departments->getCode().']-'.$departments->getName();
                }
            ]);
            }
        };

The area.addEventListener被updateareaselect去掉了,所以updateareaselect后需要重新激活eventListener,所以我创建了一个函数area_addEnventListener()

window.onload = () => {
    let country = document.querySelector("#location_country");

    country.addEventListener("change", function() {
        let form = this.closest("form");
        let data = this.name + "=" + this.value;
        fetch(form.action, {
            method: form.getAttribute("method"),
            body: data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded; charset:UTF-8"
            }
        })
        .then(response => response.text())
        .then(html => {
            let content = document.createElement("html");
            content.innerHTML = html;
            let area = content.querySelector("#location_area");
            document.querySelector("#location_area").replaceWith(area);
            area_addEnventListener(area);
        })
        .catch(error => {
            console.log(error);
        })
    });

    let area = document.querySelector("#location_area");

    area_addEnventListener(area);
}

function area_addEnventListener(area_select) {
    area_select.addEventListener("change", function() {
        let formArea = area_select.closest("form");
        let dataArea = area_select.name + "=" + area_select.value;
        fetch(formArea.action, {
            method: formArea.getAttribute("method"),
            body: dataArea,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded; charset:UTF-8"
            }
        })
        .then(response => response.text())
        .then(html => {
            let contentArea = document.createElement("html");
            contentArea.innerHTML = html;
            let department = contentArea.querySelector("#location_department");
            document.querySelector("#location_department").replaceWith(department);
        })
        .catch(error => {
            console.log(error);
        })
    });
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Symfony5 使用 AJAX 表单多选(选择列表)数据自动更新 的相关文章

随机推荐