bootstrap-select动态加载数据和多级联动

最近使用bootstrap-select在做了一个地址的联动,效果图如下

bootstrap-select动态加载数据和多级联动_第1张图片

环境相关

bootstrap 3.3.7
jquery 3.3.1
bootstrap-select 1.13.9

1、数据表结构如下

-- 地址配置表(address_config)
create table address_config
(
	option_value varchar(20) not null comment '地址编号',
	parent_id varchar(60) not null comment '父级编号',
	option_text varchar(30) comment '地址描述',
	description varchar(100) comment '描述',
	primary key (option_value, parent_id)
) COMMENT='地址配置表';

-- 初始化数据
-- 广东省
insert into address_config values('广东省','PARENT','广东省','省份');

insert into address_config values('广州市','广东省','广州市','广东省市级');

insert into address_config values('天河区','广州市','天河区','广州市县或区');
insert into address_config values('长兴街道','天河区','长兴街道','天河区街道');
insert into address_config values('元岗街道','天河区','元岗街道','天河区街道');

insert into address_config values('海珠区','广州市','海珠区','广州市县或区');

-- 云南省
insert into address_config values('云南省','PARENT','云南省','省份');

insert into address_config values('昆明市','云南省','昆明市','云南省市级');
insert into address_config values('东川区','昆明市','东川区','昆明市县或区');
insert into address_config values('嵩明县','昆明市','嵩明县','昆明市县或区');

2、Mybatis配置如下

实体

package com.flashsale.model;

public class AddressConfig {
    /**
     * 地址编号
     */
    private String optionValue;

    /**
     * 父级编号
     */
    private String parentId;

    /**
     * 地址描述
     */
    private String optionText;

    /**
     * 描述
     */
    private String description;

    /**
     * 地址编号
     * @return option_value 地址编号
     */
    public String getOptionValue() {
        return optionValue;
    }

    /**
     * 地址编号
     * @param optionValue 地址编号
     */
    public void setOptionValue(String optionValue) {
        this.optionValue = optionValue;
    }

    /**
     * 父级编号
     * @return parent_id 父级编号
     */
    public String getParentId() {
        return parentId;
    }

    /**
     * 父级编号
     * @param parentId 父级编号
     */
    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    /**
     * 地址描述
     * @return option_text 地址描述
     */
    public String getOptionText() {
        return optionText;
    }

    /**
     * 地址描述
     * @param optionText 地址描述
     */
    public void setOptionText(String optionText) {
        this.optionText = optionText;
    }

    /**
     * 描述
     * @return description 描述
     */
    public String getDescription() {
        return description;
    }

    /**
     * 描述
     * @param description 描述
     */
    public void setDescription(String description) {
        this.description = description;
    }

	@Override
	public String toString() {
		return "AddressConfig [optionValue=" + optionValue + ", parentId=" + parentId + ", optionText=" + optionText
				+ ", description=" + description + "]";
	}
}

Mapper接口

package com.flashsale.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.flashsale.model.AddressConfig;

public interface AddressConfigMapper {
	
	List selectByParentId(String parentId);
}

Mapper.xml



<mapper namespace="com.flashsale.mapper.AddressConfigMapper">
	<resultMap id="AddressConfigMap" type="com.flashsale.model.AddressConfig">
		<id column="option_value" jdbcType="VARCHAR" property="optionValue" />
		<id column="parent_id" jdbcType="VARCHAR" property="parentId" />
		<result column="option_text" jdbcType="VARCHAR" property="optionText" />
		<result column="description" jdbcType="VARCHAR" property="description" />
	resultMap>

	<select id="selectByParentId" resultMap="AddressConfigMap">
		select option_value, option_text
		from address_config
		where parent_id = #{parentId}
		order by description, option_value
	select>
mapper>

3、Service和Controller如下

Service类

package com.flashsale.service;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.flashsale.model.AddressConfig;

public interface AddressConfigService {

	List<AddressConfig> selectByParentId(String parentId);
}

Service实现类

package com.flashsale.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.flashsale.mapper.AddressConfigMapper;
import com.flashsale.model.AddressConfig;
import com.flashsale.service.AddressConfigService;

@Service("addressConfigService")
public class AddressConfigServiceImpl implements AddressConfigService {
	@Autowired
	private AddressConfigMapper addressConfigMapper;

	@Override
	public List<AddressConfig> selectByParentId(String parentId) {
		return addressConfigMapper.selectByParentId(parentId);
	}
}

Controller类

package com.flashsale.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.flashsale.helper.JsonResult;
import com.flashsale.model.AddressConfig;
import com.flashsale.service.AddressConfigService;

@RestController
@RequestMapping("/address")
public class AddressConfigController {
	@Autowired
	private AddressConfigService addressConfigService;
	
	/**
	 * 根据父级加载地址初始化数据
	 * @param parentId
	 */
	@GetMapping("/{parentId}")
	public JsonResult<AddressConfig> selectByParentId(@PathVariable("parentId") String parentId) {
		return JsonResult.success(addressConfigService.selectByParentId(parentId));
	}
}

JsonResult类

package com.flashsale.helper;

import java.util.ArrayList;
import java.util.List;

public class JsonResult<T> {
	// 状态
	private boolean success;

	// 错误码
	private String error;

	// 错误信息
	private String errorMessage;

	// 数据
	private List<T> data = new ArrayList<T>();

	// 数据总条数
	private Integer total = data != null ? data.size() : 0;

	public JsonResult() {
		super();
	}

	public boolean isSuccess() {
		return success;
	}

	public void setSuccess(boolean success) {
		this.success = success;
	}

	public String getError() {
		return error;
	}

	public void setError(String error) {
		this.error = error;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}

	public List<T> getData() {
		return data;
	}

	public void setData(List<T> data) {
		this.data = data;
	}

	public Integer getTotal() {
		return total;
	}

	public void setTotal(Integer total) {
		this.total = total;
	}
	
	public static <T> JsonResult<T> success() {
		return success(null);
	}
	
	public static <T> JsonResult<T> success(List<T> data) {
		JsonResult<T> jsonResult = new JsonResult<T>();
		jsonResult.success = true;
		jsonResult.error = null;
		jsonResult.errorMessage = null;
		jsonResult.data = data;
		return jsonResult;
	}
	
	public static <T> JsonResult<T> success(T row) {
		JsonResult<T> jsonResult = new JsonResult<T>();
		jsonResult.success = true;
		jsonResult.error = null;
		jsonResult.errorMessage = null;
		jsonResult.data.add(row);
		jsonResult.total = 1;
		return jsonResult;
	}
	
	public static <T> JsonResult<T> error(String error, String errorMessage) {
		JsonResult<T> jsonResult = new JsonResult<T>();
		jsonResult.success = false;
		jsonResult.error = error;
		jsonResult.errorMessage = errorMessage;
		jsonResult.data = null;
		return jsonResult;
	}
}

4、返回的JSON数据格式如下

bootstrap-select动态加载数据和多级联动_第2张图片

5、前端页面及JS

引入相关的CSS和JS


<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>用户管理title>
		
		<link rel="stylesheet" type="text/css" href="css/plugins/bootstrap.min.css">
		<link rel="stylesheet" type="text/css" href="css/plugins/bootstrap-select.min.css">
	head>
	<body>
        <div class="btn-group">
			<button id="btn_add" class="btn btn-primary btn-sm" data-toggle="modal" 
				data-target="#addUserModal" data-whatever="新增">
				<span class="glyphicon glyphicon-plus" aria-hidden="true">span>
				新增
			button>
		div>
        
		<div class="modal fade" id="addUserModal" tabindex="-1" role="dialog" aria-labelledby="addUserModalLabel" 
			aria-hidden="true" data-backdrop="static" data-keyboard="false">
		    <div class="modal-dialog" style="width:800px">
		        <div class="modal-content">
		            <div class="modal-header">
		                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×button>
		                <h4 class="modal-title" id="addUserModalLabel">h4>
		            div>
		            <div class="modal-body">
		            	<form class="form-horizontal" id="userForm" method="POST" role="form" autocomplete="off">
							<div class="form-group form-inline">
								<label class="col-sm-2 control-label">地址label>
								<div class="col-sm-8">
									<select class="selectpicker form-control" onchange="initCity()" id="province" name="province">
										<option value="">--省份--option>
			    					select>
			    					<select class="selectpicker form-control" onchange="initRegion()" id="city" name="city">
			    						<option value="">--城市--option>
			    					select>
			    					<select class="selectpicker form-control" onchange="initStreet()" id="region" name="region">
			    						<option value="">--县区--option>
			    					select>
			    					<select class="selectpicker form-control" id="street" name="street">
			    						<option value="">--街道--option>
			    					select>
								div>
							div>
							
							<div class="form-group">
								<label for="userEmail" class="col-sm-2 control-label">label>
								<div class="col-sm-8">
									<input type="text" class="form-control" id="userArea" name="userArea" placeholder="输入详细地址" />
								div>
							div>
						form>
		            div>
		        div>
		    div>
		div>
		
		<script src="js/plugins/jquery-3.3.1.min.js">script>
		<script src="js/plugins/bootstrap.js">script>
		<script src="js/plugins/bootstrap-select.min.js">script>
		<script src="js/userInfo.js">script>
	body>
html>

userInfo.js

$(document).ready(function(){
	// 地区下拉框初始化
	$("#province").selectpicker({width:130, liveSearch: true, liveSearchPlaceholder: "搜索" });
	$("#city").selectpicker({width:120, liveSearch: true, liveSearchPlaceholder: "搜索" });
	$("#region").selectpicker({width:120, liveSearch: true, liveSearchPlaceholder: "搜索" });
	$("#street").selectpicker({width:120});
	
	// 动态加载省份选项数据
	initSelectOptions("province", "PARENT");
});// onReady

/**
 * 动态生成select选项
 * @param selectId
 * @param parentId
 * @returns
 */
function initSelectOptions(selectId, parentId) {
	var selectObj = $("#" + selectId);
	$.ajax({
        url : "/flashsale/address/" + parentId,
        async : false,
        type : "GET",
        success : function(result) {
        	if (result.success) {
        		var configs = result.data;
        		selectObj.find("option:not(:first)").remove();
        		for (var i in configs) {
        			var addressConfig = configs[i];
        			var optionValue = addressConfig.optionValue;
        			var optionText = addressConfig.optionText;	
        			selectObj.append(new Option(optionText, optionValue));
        		}
        		
        		// 刷新select
    			selectObj.selectpicker('refresh');
        	} else {
        		toastr.error('获取['+ parentId + ']信息失败,原因:' + result.errorMessage);
        	}
        },
        error : function(result) {
        	toastr.error('获取['+ parentId + ']信息失败,原因:' + result.errorMessage);
        }
	});// ajax
}

/**
 * 根据选择的省份动态初始化城市options
 * @returns
 */
function initCity() {
	// 当省份变动时,初始化城市和清空县区和街道
	var provinceSel = $("#province").val();
	initSelectOptions("city", provinceSel);
	$("#region").find("option:not(:first)").remove();
	$("#region").selectpicker('refresh');
	$("#street").find("option:not(:first)").remove();
	$("#street").selectpicker('refresh');
}

/**
 * 根据选择的城市动态初始化区域options
 * @returns
 */
function initRegion() {
	// 选择城市
	var citySel = $("#city").val();
	initSelectOptions("region", citySel);
}

/**
 * 根据选择的县区动态初始化街道options
 * @returns
 */
function initStreet() {
	// 选择县区
	var regionSel = $("#region").val();
	initSelectOptions("street", regionSel);
}

你可能感兴趣的:(bootstrap)