Bootstrap每天必學(xué)之級(jí)聯(lián)下拉菜單
本文將介紹自定義的bootstrap級(jí)聯(lián)下拉菜單,主要應(yīng)用場(chǎng)合有省市級(jí)關(guān)聯(lián)菜單等等,那么就先拿這個(gè)例子來(lái)講,當(dāng)然其他場(chǎng)景的關(guān)聯(lián)菜單也同樣適用。說(shuō)實(shí)話(huà),封裝好一個(gè)通用的組件還是需要花費(fèi)很多精力的和時(shí)間的,所謂通用,自然要考慮周全,嘆!這次整理的Bootstrap關(guān)聯(lián)select,里面也涉及到了很多jquery、ajax、springMVC等等知識(shí)點(diǎn),可謂包羅萬(wàn)象!
首先,請(qǐng)?jiān)试S我代表該自定義組件做一番小小的介紹。
“hi,你好,我叫yunm.combox.js,主人給我起的名字,其實(shí)呢,挺俗的。我主要通過(guò)為select組件增加兩個(gè)自定義屬性來(lái)完成相應(yīng)的數(shù)據(jù)加載,數(shù)據(jù)請(qǐng)求使用了ajax,后端數(shù)據(jù)處理使用了springMVC(當(dāng)然其他方式也可以,只需要返回對(duì)應(yīng)的json數(shù)據(jù)即可),使用起來(lái)呢,就非常非常簡(jiǎn)單了!”
一、界面效果
當(dāng)然了,從界面上完全看不出來(lái)一個(gè)組件封裝的好壞,但至少,你感覺(jué)很簡(jiǎn)潔漂亮,那么好了,有了這層印象,你是否有興趣繼續(xù)看下去?我想答案是肯定的。
二、使用方法
①、procity.jsp
首先呢,在頁(yè)面上加載yunm.combox.js(稍候介紹,至于其他的bootstrap的css和js,不在本章介紹范圍內(nèi),略過(guò)),同時(shí)呢,創(chuàng)建兩個(gè)select,具體格式見(jiàn)如下:
<script type="text/javascript" src="${ctx}/components/yunm/yunm.combox.js"></script> <div class="form-group"> <div class="row"> <div class="col-md-6"> <select name="province_code" class="form-control combox" ref="city_select" refUrl="${ctx}/procity?pro_code={value}&city_code=HSLY"> </select> </div> <div class="col-md-6"> <select name="city_code" id="city_select" class="form-control"> </select> </div> </div> </div> <script type="text/javascript"> <!-- $(function() { if ($.fn.combox) { $("select.combox", $p).combox(); } }); //--> </script>
·兩個(gè)select組件,一個(gè)為province_code、一個(gè)為city_code。
·省級(jí)菜單上增加了兩個(gè)屬性。
ref指定關(guān)聯(lián)菜單為市級(jí)菜單city_select
refUrl指定菜單獲取數(shù)據(jù)的URL
pro_code作為獲取市級(jí)數(shù)據(jù)的關(guān)鍵因子
{value}呢,則為通配符,稍候在介紹組件的時(shí)候繼續(xù)講到
city_code=HSLY,主要用于選中指定的省市菜單,諸如上文中的(河南、洛陽(yáng)),如果不選中,則city_code=為空
·class=”combox” 為該省級(jí)下拉框增加jquery選擇器
·頁(yè)面加載完畢后執(zhí)行combox組件的關(guān)鍵方法,下面詳細(xì)介紹
②、yunm.combox.js
現(xiàn)在我們來(lái)看看關(guān)鍵的組件內(nèi)容吧!
(function($) { var _onchange = function(event) { var $ref = $("#" + event.data.ref); if ($ref.size() == 0) return false; var refUrl = event.data.refUrl; var value = encodeURIComponent(event.data.$this.val()); YUNM.debug(value); $.ajax({ type : 'POST', dataType : "json", url : refUrl.replace("{value}", value), cache : false, data : {}, success : function(response) { $ref.empty(); addHtml(response, $ref); $ref.trigger("change").combox(); }, error : YUNM.ajaxError }); }; var addHtml = function(response, $this) { var json = YUNM.jsonEval(response); if (!json) return; var html = ''; $.each(json, function(i) { if (json[i]) { html += '<option value="' + json[i].value + '"'; if (json[i].selected) { html += ' selected="' + json[i].selected; } html += '">' + json[i].name + '</option>'; } }); $this.html(html); }; $.extend($.fn, { combox : function() { return this.each(function(i) { var $this = $(this); var value = $this.val() || ''; var ref = $this.attr("ref"); var refUrl = $this.attr("refUrl") || ""; if (refUrl) { refUrl = refUrl.replace("{value}", encodeURIComponent(value)); } if (refUrl) { $.ajax({ type : 'POST', dataType : "json", url : refUrl, cache : false, data : {}, success : function(response) { addHtml(response, $this); if (ref && $this.attr("refUrl")) { $this.unbind("change", _onchange).bind("change", { ref : ref, refUrl : $this.attr("refUrl"), $this : $this, }, _onchange).trigger("change"); } }, error : YUNM.ajaxError }); } }); } }); })(jQuery);
·通過(guò)$.extend($.fn, { combox : function() {為jquery增加一個(gè)叫combox的底層(可以查詢(xún)jquery幫助文檔)方法。
·通過(guò)(function($){_onchange、addHtml})(jQuery);為該組件在頁(yè)面初始加載時(shí)創(chuàng)建兩個(gè)方法onchange和addHtml,至于(function($) {})(jQuery);我想你如果不了解的話(huà),趕緊百度吧!
·先來(lái)看combox 方法
獲取ref、refUrl,通過(guò)ajax向refUrl請(qǐng)求省級(jí)菜單數(shù)據(jù),當(dāng)獲取成功后,通過(guò)addHtml方法將json轉(zhuǎn)換后的option綁定到省級(jí)菜單select上
然后呢,為省級(jí)菜單select綁定change事件,傳遞的參數(shù)為ref(市級(jí)菜單)、refUrl(市級(jí)數(shù)據(jù)獲取的url)、$this(省級(jí)菜單,便于change事件獲取對(duì)應(yīng)選中項(xiàng),如效果圖中的河南)
通過(guò)trigger方法立即執(zhí)行change事件,便于獲取對(duì)應(yīng)的市級(jí)菜單內(nèi)容。
·再來(lái)看_onchange方法,主要是點(diǎn)擊省級(jí)菜單時(shí)觸發(fā),用于獲取市級(jí)菜單列表
refUrl,向服務(wù)端請(qǐng)求的URL
value,用于獲取省級(jí)菜單的選中項(xiàng)目,然后通過(guò)該value值獲取省級(jí)對(duì)應(yīng)的市級(jí)菜單
$ref.empty();用于清空市級(jí)菜單
通過(guò)ajax繼續(xù)獲取市級(jí)菜單內(nèi)容,然后通過(guò)addHtml方法添加到市級(jí)菜單中。
·addHtml方法
通過(guò)jsonEval方法對(duì)服務(wù)端傳遞回來(lái)的數(shù)據(jù)進(jìn)行eval(eval('(' + data + ')'),如有不懂,可百度)方法處理,否則會(huì)出錯(cuò)。
$.each(json, function(i) {遍歷json,通過(guò)jquery創(chuàng)建option對(duì)象,然后加入到select中。
③、ProcityController
前端介紹完了,我們回到后端進(jìn)行介紹,當(dāng)然了,你也可以忽略本節(jié),因?yàn)椴皇撬玫年P(guān)聯(lián)數(shù)據(jù)都通過(guò)springMVC這種方法獲取,那么先預(yù)覽一下代碼吧!
package com.honzh.spring.controller; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import com.honzh.biz.database.entity.City; import com.honzh.biz.database.entity.Option; import com.honzh.biz.database.entity.Provincial; import com.honzh.common.util.JsonUtil; import com.honzh.spring.service.CityService; import com.honzh.spring.service.ProvincialService; @Controller @RequestMapping(value = "/procity") public class ProcityController extends BaseController { private static Logger logger = Logger.getLogger(ProcityController.class); /** * 當(dāng)傳遞city_code,則表明下拉框要被選中,否則不選中 */ @RequestMapping("") public void index(@RequestParam(value = "city_code", required = false) String city_code, @RequestParam(value = "pro_code", required = false) String pro_code, HttpServletResponse response) { try { logger.debug("獲取所在地區(qū)" + city_code + ", 省" + pro_code); // 如果pro_code為””,則表明要獲取城市菜單,否則獲取市級(jí)菜單 if (!pro_code.equals("")) { Integer pro_id = ProvincialService.getInstance().getByProvincialcode(pro_code).getId(); List<City> citys = CityService.getInstance().getCitysByProvincialId(pro_id); List<Option> coptions = new ArrayList<Option>(citys.size()); for (City city : citys) { Option coption = new Option(); coption.setId(city.getId()); coption.setName(city.getCname()); coption.setValue(city.getCode()); // 市級(jí)菜單被選中 if (city_code != null && !city_code.equals("")) { if (city.getCode().equals(city_code)) { coption.setSelected("selected"); } } coptions.add(coption); } renderJson(response, coptions); } else { List<Provincial> provincials = ProvincialService.getInstance().getProvincials(); // 轉(zhuǎn)換成標(biāo)準(zhǔn)的option屬性(name,value,selected) List<Option> options = new ArrayList<Option>(provincials.size()); // 被選中的省市 // 則說(shuō)明是展示頁(yè)面,此時(shí)需要為省級(jí)菜單和市級(jí)菜單設(shè)置選擇項(xiàng) if (city_code != null && !city_code.equals("")) { Provincial selected_provincial = ProvincialService.getInstance().getProvincialByCitycode(city_code); pro_code = selected_provincial.getProcode(); } else { pro_code = provincials.get(0) == null ? "" : provincials.get(0).getProcode(); } for (Provincial provincial : provincials) { Option option = new Option(); option.setId(provincial.getId()); option.setName(provincial.getProname()); option.setValue(provincial.getProcode()); if (!pro_code.equals("") && provincial.getProcode().equals(pro_code)) { option.setSelected("selected"); } options.add(option); } renderJson(response, JsonUtil.toJson(options)); } } catch (Exception e) { logger.error(e.getMessage()); logger.error(e.getMessage(), e); renderJson(response, null); } } }
@RequestParam(value = "city_code", required = false) String city_code,對(duì)于RequestParam注解,其實(shí)非常好用,這里就不多做解釋?zhuān)皇峭茝V一下,固定個(gè)數(shù)的參數(shù),用該注解更易于代碼的維護(hù)。
ProvincialService類(lèi)、CityService類(lèi)就是兩個(gè)單例,盡量把數(shù)據(jù)放置在內(nèi)存當(dāng)中,減少查詢(xún)數(shù)據(jù)庫(kù)的次數(shù),稍候貼出來(lái)一個(gè)例子。
Option類(lèi)就是單純的封裝前端option組件的關(guān)鍵屬性,便于組件的通用化。
renderJson(response, JsonUtil.toJson(options));將數(shù)據(jù)json化后返回,稍候貼上詳細(xì)代碼。
④、ProvincialService.java
只貼出來(lái)代碼例子,不做詳細(xì)解釋?zhuān)吘共皇潜菊轮攸c(diǎn)。
package com.honzh.spring.service; import java.util.ArrayList; import java.util.List; import com.honzh.biz.database.entity.City; import com.honzh.biz.database.entity.Provincial; import com.honzh.biz.database.mapper.ProvincialMapper; import com.honzh.common.spring.SpringContextHolder; public class ProvincialService { private static Object lock = new Object(); private static ProvincialService config = null; private ProvincialService() { provincials = new ArrayList<Provincial>(); ProvincialMapper mapper = SpringContextHolder.getBean(ProvincialMapper.class); provincials.addAll(mapper.getProvincials()); } public static ProvincialService getInstance() { synchronized (lock) { if (null == config) { config = new ProvincialService(); } } return (config); } public Provincial getByProvincialcode(String provincial_code) { for (Provincial provincial : provincials) { if (provincial.getProcode().equals(provincial_code)) { return provincial; } } return null; } private List<Provincial> provincials = null; public List<Provincial> getProvincials() { return provincials; } public Provincial getProvincialByCitycode(String city_code) { City city = CityService.getInstance().getCityByCode(city_code); for (Provincial provincial : provincials) { if (provincial.getId().intValue() == city.getProid().intValue()) { return provincial; } } return null; } public Provincial getProvincialByCode(String province_code) { for (Provincial provincial : provincials) { if (provincial.getProcode().equals(province_code)) { return provincial; } } return null; } }
⑤、renderJson方法
/** * 如果出錯(cuò)的話(huà),response直接返回404 */ protected void renderJson(HttpServletResponse response, Object responseObject) { PrintWriter out = null; try { if (responseObject == null) { response.sendError(404); return; } // 將實(shí)體對(duì)象轉(zhuǎn)換為JSON Object轉(zhuǎn)換 String responseStr = JsonUtil.toJson(responseObject); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); out = response.getWriter(); out.append(responseStr); logger.debug("返回是:" + responseStr); } catch (IOException e) { logger.error(e.getMessage()); logger.error(e.getMessage(), e); } finally { if (out != null) { out.close(); } } }
如果大家還想深入學(xué)習(xí),可以點(diǎn)擊jQuery級(jí)聯(lián)菜單特效匯總、Javascript級(jí)聯(lián)菜單特效匯總進(jìn)行學(xué)習(xí)。
如果大家還想深入學(xué)習(xí)Bootstrap,可以點(diǎn)擊這里進(jìn)行學(xué)習(xí),再為大家附兩個(gè)精彩的專(zhuān)題:Bootstrap學(xué)習(xí)教程 Bootstrap實(shí)戰(zhàn)教程
本文系列教程整理到:Bootstrap基礎(chǔ)教程 專(zhuān)題中,歡迎點(diǎn)擊學(xué)習(xí)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
- BootStrap中關(guān)于Select下拉框選擇觸發(fā)事件及擴(kuò)展
- Bootstrap select多選下拉框?qū)崿F(xiàn)代碼
- bootstrap下拉列表與輸入框組結(jié)合的樣式調(diào)整
- Bootstrap每天必學(xué)之下拉菜單
- Bootstrap模塊dropdown實(shí)現(xiàn)下拉框響應(yīng)
- Bootstrap框架下下拉框select搜索功能
- Bootstrap Table 在指定列中添加下拉框控件并獲取所選值
- bootstrap中selectpicker下拉框使用方法實(shí)例
- Bootstrap中的Dropdown下拉菜單更改為懸停(hover)觸發(fā)
- IE11下CKEditor在Bootstrap Modal中下拉問(wèn)題的解決
相關(guān)文章
Javascript獲取當(dāng)前日期的農(nóng)歷日期代碼
這篇文章主要介紹了利用Javascript獲取當(dāng)前日期的農(nóng)歷日期代碼,很實(shí)用,需要的朋友可以參考下2014-10-10微信小程序?qū)崿F(xiàn)購(gòu)物車(chē)代碼實(shí)例詳解
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)購(gòu)物車(chē)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08基于函數(shù)執(zhí)行的踩坑(addEventListener)
這篇文章主要介紹了基于函數(shù)執(zhí)行的踩坑(addEventListener),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01JS?中在嚴(yán)格模式下?this?的指向問(wèn)題
這篇文章主要介紹了JS?中在嚴(yán)格模式下this的指向問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-095個(gè)書(shū)寫(xiě)JavaScript代碼的壞習(xí)慣,看看你中槍了沒(méi)?
這篇文章主要介紹了5個(gè)書(shū)寫(xiě)JavaScript代碼的壞習(xí)慣,看看你中槍了沒(méi)?,本文指出了你沒(méi)有使用命名空間、變量定義的東一個(gè)西一個(gè)、Javascript的變量范圍、Javascript的面向?qū)ο?、new關(guān)鍵字等問(wèn)題,需要的朋友可以參考下2014-11-11layui實(shí)現(xiàn)左側(cè)菜單點(diǎn)擊右側(cè)內(nèi)容區(qū)顯示
這篇文章主要為大家詳細(xì)介紹了layui實(shí)現(xiàn)左側(cè)菜單點(diǎn)擊右側(cè)內(nèi)容區(qū)顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07Bootstrap開(kāi)發(fā)中Tab標(biāo)簽頁(yè)切換圖表顯示問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于Bootstrap開(kāi)發(fā)中Tab標(biāo)簽頁(yè)切換圖表顯示問(wèn)題的解決方法,文中通過(guò)圖文以及示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07原生js實(shí)現(xiàn)文件上傳、下載、封裝等實(shí)例方法
在本篇文章里小編給各位整理的是關(guān)于原生js實(shí)現(xiàn)文件上傳、下載、封裝等實(shí)例方法,需要的朋友們可以參考學(xué)習(xí)下。2020-01-01