select three-level linkage selection - select based on layui

Select three-level linkage selection—based on Layui

Layui is an open source Web UI component library. layui adopts its own minimalist modular specification, and follows the development mode of native HTML/CSS/JS, which is very easy to use and can be used out of the box. It is an indispensable learning artifact for front-end and back-end beginners. (ps: For people like the author who write ugly front-end pages, it is simply good news!)

There are two main ways to use it, one is to directly download the source code of layui; the other is to use online reference (that is, to use it by non-downloading). The author prefers to use it by downloading the source code.

Attach the website of Layui: https://layui.org.cn/index.html

insert image description here

1. Demand

The requirements are like this. When I was writing a mall project, I involved the form submitted by the supplier. There is a supplier address selection in the form that is applied to the select box. When I first learned html, I also wrote a selection box many times. But the content options in the selection box are already fixed. As follows:

<select name="pets" id="pet-select">
    <option value="">--Please choose an option--</option>
    <option value="dog">Dog</option>
    <option value="cat">Cat</option>
    <option value="hamster">Hamster</option>
    <option value="parrot">Parrot</option>
    <option value="spider">Spider</option>
    <option value="goldfish">Goldfish</option>
</select>
<!--在select选择框中已经提前预写了option选项,可以直接选择。但是这种选择的方式有一个非常明显的弊端,如果待选项数目很多,挨个去写很浪费时间而且代码还很臃肿,不美观。-->

The requirement of this project is that all provinces, cities, counties (districts) in the country need to be linked together. If it is written in the most primitive way, it will undoubtedly be a disaster. So I tried another way, which is to read the content of the selection box from the database, and the selection of multiple selection boxes is linked (that is, if you choose Guangdong Province, then you will not be able to select Hangzhou City, you can only select from Select from all prefecture-level cities in Guangdong Province).

2. Analysis and front-end code

First of all, it is necessary to write the form that the entire supplier needs to submit to form a rough outline.

To read data from the background database, front-end and back-end interactions are required, so the realization of the three-level linkage in this project mainly relies on jQuery.

The author downloaded the source code of jQuery and layui, and then directly attached it to the project.

This article mainly focuses on the linkage selection of the three selection boxes, so other contents are simplified. code attached

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>供应商登记</title>
    <script type="text/javascript" src="../../../static/jquery-3.6.3.min.js"></script>
    <link rel="stylesheet" href="../../../static/layui/css/layui.css">
    <script type="text/javascript" src="../../../static/layui/layui.js"></script>
    <script type="text/javascript" src="../../../static/js/registerVendors.js"></script>
</head>
<body onload="load()">
        <div class="layui-fluid">
            <div class="layui-row">
                <h1 style="text-align: center">供应商</h1>
            </div>
          <form class="layui-form"  action="/registerVendors" method="get">
              <div class="layui-form-item">
                  <label class="layui-form-label">注册地址</label>
                  <div class="layui-input-block">
                      <select id="province" name="vendorsProvince" lay-filter="changeProvince"  >
                      </select>
                      <select id="city" name="vendorsCity" lay-filter="changeCity" >
                      </select>
                      <select id="region" name="vendorsRegion">
                      </select>
                  </div>
              </div>
          </form>
        </div>
</body>
</html>

In this code, the registered address is represented by three select boxes. lay-filterActs like a selector.

The effect achieved is: when the user selects the province, the system will load the prefecture-level city, and only the prefecture-level city will load the district. If someone intentionally skips the selection first, then nothing will be selectable. This ensures the correctness and simplicity of the selection.

Such an implementation needs to be matched with js to achieve the effect of responsive loading

layui.use('form',function () {
    
    
    form = layui.form;
    loadCities();
    loadRegions();

})
layui.use('layer',function () {
    
    
     layer=layui.layer;
})

//页面开始就加载省份
function load() {
    
    
    $().ready(function () {
    
    
        $.ajax({
    
    
            type: 'post',
            url: '/getProvince',
            cache: false,
            async: true,
            dataType: 'json',
            success(data) {
    
    
                console.log(data)
               let selectProvince= document.getElementById("province");
                selectProvince.add(new Option("请选择对应的省份","0"))
                let option=null;
                for (let i = 0; i < data.length; i++) {
    
    
                  option = new Option(data[i].provinceName,data[i].provinceId);

                    selectProvince.add(option)
                }
                console.log("添加完毕!")
                form.render('select')
                form.render();
                // $("#province").html(options);
            },
            error() {
    
    
                console.log("进入了error")
                layer.confirm('省份加载暂时出现了点问题!', {
    
    icon: 2, btn: ['好的,回主页吧', '去登陆页'], title: '错误信息'}, function () {
    
    
                        window.location.href = '/main'
                    },
                    function () {
    
    
                        window.location.href = '/login'
                    })
            }
        })

    })
}

//选择城市
function loadCities() {
    
    
    form.on('select(changeProvince)', function () {
    
    
        $("#city").html('')
        //alert("改变方法执行了!")
        let provinceId = $("#province option:selected").val();
        //let provinceId = data.val();
        $.ajax({
    
    
            type: 'post',
            url: '/getCities',
            cache: false,
            async: true,
            data: {
    
    "provinceId": provinceId},
            //  contentType:"application/json",
            dataType: 'json',
            success(data) {
    
    
                console.log(data)
                let selectCities = document.getElementById("city");
                selectCities.add(new Option("请选择对应的城市", "0"));
                let option = null;
                for (let i = 0; i < data.length; i++) {
    
    
                    option = new Option(data[i].cityName, data[i].cityId);
                    selectCities.add(option)
                }
                form.render('select')
                form.render();
            },
            error() {
    
    
                console.log("进入了error")
                layer.confirm('市加载暂时出现了点问题!', {
    
    icon: 2, btn: ['好的,回主页吧', '去登陆页'], title: '错误信息'}, function () {
    
    
                        window.location.href = '/main'
                    },
                    function () {
    
    
                        window.location.href = '/login'
                    })
            }
        })
    })
}

//选择地区
function loadRegions () {
    
    
    form.on('select(changeCity)',function () {
    
    
        $("#region").html('');
        let cityId=$("#city option:selected").val();
        $.ajax({
    
    
            type:'post',
            url:'/getRegions',
            cache:false,
            async:true,
            data: {
    
    "cityId":cityId},
            dataType:'json',
            success(data){
    
    
                let selectRegions = document.getElementById("region");
                selectRegions.add(new Option("请选择对应的区",0))
                let option=null
                for (let i=0;i<data.length;i++){
    
    
                    option=new Option(data[i].regionName,data[i].regionId);
                    selectRegions.add(option);
                }
                form.render('select')
                form.render();

            },
            error() {
    
    
                console.log("进入了error")
                layer.confirm('区加载暂时出现了点问题!', {
    
    icon: 2, btn: ['好的,回主页吧', '去登陆页'], title: '错误信息'}, function () {
    
    
                        window.location.href = '/main'
                    },
                    function () {
    
    
                        window.location.href = '/login'
                    })
            }

        })
    })
}

The way to achieve it:

  • Province loading

First, as soon as the page is loaded, onload=load()the specific name of each province is loaded by loading. That is, the loading of the province is carried out along with the loading of the page. The content of the specific province loaded is obtained from the back-end database through the ajax method of jQuery. The result returned by the backend is in json format (dataType: json).

When the background returns data successfully, it will enter the success function, and data is the actual result returned by the backend. Then analyze the json result returned by the backend in detail. The format returned by the author is {xxxId: xxxName}.

Finally, through the option object, add it to the select selection box. The last thing to pay attention to is form.render('select'), which needs to be refreshed after loading. This is a huge pit.

  • prefecture-level city loading

After the provinces are loaded, the loading of prefecture-level cities is different from the loading of provinces. We need to obtain the specific id of the province selected by the user after the province is loaded and pass it to the backend. The backend selects the corresponding id according to the id of the province. All prefecture-level cities.

This function requires the use of form.on()a function. The first parameter in the function is similar to a selector. Once the province is selected, the second parameter will be executed immediately, that is, the corresponding function will load the prefecture-level city. Still It is an asynchronous request through jQuery's ajax method. The returned format is still in json format.

Finally, the select selection box is realized by setting the option object.

Note that $("#city").html(''). This item is used for initialization. If the wrong province is selected and needs to be corrected, the previously selected content will be completely cleared, which is very important.

  • District (County) Loading

The loading of districts (counties) is similar to the loading of prefecture-level cities, but it uses the id of the corresponding prefecture-level city to obtain all the names of districts (counties) under the corresponding prefecture-level city. The operation is similar to prefecture-level city loading.

3. Backend implementation

In this project, the author's backend uses the SpringBoot framework. The loading of the specific content of the selection box is realized through the mvc mode.

  • Entity class design
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Province {
    
    
    @Column(name = "province_id")
    private String provinceId;

    @Column(name = "province_name")
    private String provinceName;
}

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class City {
    
    

    @Column(name = "city_id")
    private String cityId;
    @Column(name = "city_name")
    private String cityName;

}

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Region {
    
    
    @Column(name = "region_id")
    private String regionId;
    @Column(name = "region_name")
    private String regionName;
}

All three use lombok to load setter and getter methods and construction methods. @ColumnThe role of is to match the fields of the entity class with the fields in the database table in advance to prevent mismatching and error reporting later.

  • Database Design

The database design is relatively simple this time, only one table is designed, and some data is randomly filled for testing.

CREATE TABLE IF NOT EXISTS address(
        province_id  VARCHAR(20)  NOT NULL  ,
        province_name VARCHAR(20) NOT NULL ,
        city_id VARCHAR(20) NOT NULL ,
        city_name VARCHAR(20) NOT NULL ,
        region_id VARCHAR(20) NOT NULL  PRIMARY KEY ,
        region_name VARCHAR(20) NOT NULL

    );
    
-- 手动添加一些数据
INSERT INTO address VALUES ('p1','北京','c1','北京','r1','房山区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r2','通州区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r3','丰台区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r4','东城区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r5','西城区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r6','崇文区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r7','朝阳区');
INSERT INTO address VALUES ('p1','北京','c1','北京','r8','海淀区');
INSERT INTO address VALUES ('p2','上海','c1','上海','p2r1','嘉定区');

INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r3','徐汇区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r4','长宁区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r5','静安区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r6','普陀区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r7','宝山区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r8','青浦区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r9','奉贤区');
INSERT INTO address VALUES ('p2','上海','p2c1','上海','p2r10','金山区');

INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r1','滨海新区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r2','宁河区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r3','和平区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r4','河北区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r5','河东区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r6','河西区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r7','南开区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r8','武清区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r9','静海区');
INSERT INTO address VALUES ('P3','天津','p3c1','天津','p3r10','蓟州区');

The region_id is set as the primary key in the database because when loading data, provinces and cities may be repeated, and only the district name is unique in this table.

  • Persistence layer

Java code implementation


@Mapper
@Repository
public interface LoadAddressData {
    
    
    /**
     * @return
     */

   List<Province> getProvince();


    /**
     *
     * @param provinceId 省份的id值
     * @return 返回对应省份id所对应的所有城市
     */
   List<City> getCities(@Param("provinceId") String provinceId);

    /**
     *
     * @param cityId 对应城市的id
     * @return 返回对应id城市的所有区
     */
   List<Region>getRegions(@Param("cityId")String cityId);


}

The results returned by the three methods are all in the form of a list, and the contents in the list are all objects

Realized through the mapping file of mybatis

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mail.dao.vendorsDao.LoadAddressData">
    <!--命名空间-->
    
    <resultMap id="resultMapProvince" type="com.example.mail.entity.Province">
        <result column="province_id" property="provinceId"/>
        <result column="province_name" property="provinceName"/>
    </resultMap>
    <!--resultMap的主要作用是将结果集映射到具体的数据库字段名称上去-->
    
    <select id="getProvince" resultMap="resultMapProvince" resultType="list">
        SELECT DISTINCT province_id,province_name FROM address;
    </select>
    <!--执行查询所有省份的方法-->
    
    <!--根据省份id查询所有的城市-->
    <resultMap id="resultMapCities" type="com.example.mail.entity.City">
        <result column="city_id" property="cityId"/>
        <result column="city_name" property="cityName"/>
        <result column="province_id" property="provinceId"/>
    </resultMap>
    <select id="getCities" parameterType="java.lang.String" resultType="list" resultMap="resultMapCities">
           SELECT DISTINCT city_id,city_name FROM address WHERE province_id=#{provinceId};
    </select>
    
    
    <!--根据城市的id查询所有区(县)-->
    <resultMap id="resultMapRegions" type="com.example.mail.entity.Region">
        <result column="city_id" property="cityId"/>
        <result column="region_id" property="regionId"/>
        <result column="region_name" property="regionName"/>
    </resultMap>
    <select id="getRegions" parameterType="java.lang.String" resultType="list" resultMap="resultMapRegions">
        SELECT DISTINCT region_id,region_name FROM address WHERE city_id=#{cityId};
    </select>
</mapper>
  • Service layer code implementation
public interface LoadAddressDataService {
    
    

    /**
    *获取所有的省份
    */
   List<Province> getProvince();

   /**
    *
    * @param provinceId 省份的id值
    * @return 返回对应省份id所对应的所有城市
    */
   List<City> getCities(@Param("provinceId") String provinceId);

   /**
    *
    * @param cityId 对应城市的id
    * @return 返回对应id城市的所有区
    */
   List<Region>getRegions(@Param("cityId")String cityId);
}

@Service
public class LoadAddressDataServiceImpl implements LoadAddressDataService {
    
    

    @Autowired
    private LoadAddressData loadAddressData;
    
    /**
    *获取所有的省份
    */
    @Override
    public List<Province> getProvince() {
    
    
        return loadAddressData.getProvince();
    }

    /**
     * @param provinceId 省份的id值
     * @return 返回对应省份id所对应的所有城市
     */
    @Override
    public List<City> getCities(String provinceId) {
    
    
        return loadAddressData.getCities(provinceId);
    }

    /**
     * @param cityId 对应城市的id
     * @return 返回对应id城市的所有区
     */
    @Override
    public List<Region> getRegions(String cityId) {
    
    
        return loadAddressData.getRegions(cityId);
    }
}
  • Control layer implementation
@Controller
public class LoadAddressDataController {
    
    
    @Autowired
    private LoadAddressDataService loadAddressDataService;

    @RequestMapping("/getProvince")
    @ResponseBody
    public String getProvince(){
    
    
        List<Province> provinces = loadAddressDataService.getProvince();
        return JSON.toJSONString(provinces);
    }


    @RequestMapping("/getCities")
    @ResponseBody
    public String getCities( String provinceId){
    
    
        System.out.println("获取到的省份id为"+provinceId);
        List<City> cities = loadAddressDataService.getCities(provinceId);
        return JSON.toJSONString(cities);
    }


    @RequestMapping("/getRegions")
    @ResponseBody
    public String getRegions(String cityId){
    
    
        System.out.println("获取到城市id为"+cityId);
        List<Region> regions = loadAddressDataService.getRegions(cityId);
        return JSON.toJSONString(regions);
    }

}

It can be seen that the last returned strings in the control layer code are all strings in json format. This is because the three ajax requests in the front-end js file are all set in dataTypejson

  • Achieved effect

select province

insert image description here


If you bypass the selection of cities, you cannot continue to select districts and counties

insert image description here


Finally select the district

insert image description here

This is over!

insert image description here

Guess you like

Origin blog.csdn.net/qq_50824019/article/details/130062326