1. 程式人生 > 其它 >使用input+datalist簡單實現實時匹配的可編輯下拉列表-並解決選定後瀏覽器預設只顯示value的可讀性問題

使用input+datalist簡單實現實時匹配的可編輯下拉列表-並解決選定後瀏覽器預設只顯示value的可讀性問題

問題背景

最近小夥伴提了一個希望提高後臺下拉列表可操作性的需求,原因是下拉列表選項過多,每次下拉選擇比較費時費力且容易出錯,硬著頭皮啃了啃前端知識,網上搜尋了一些下拉列表實現的資料,這裡總結一下。
PS: 以下所有程式碼實現效果截圖均為chrome瀏覽器下效果,其他瀏覽器效果可能有一定差別,比如datalist在firefox和chrome下就有較明顯差別,這不是本文重點這裡不做討論。

最簡單的下拉列表實現

在HTML中傳統顯示下拉框的方法是使用select+option標籤組合實現:

<select name="staff" id="id_list">
  <option value="10">張三</option>
  <option value="11">李四</option>
  <option value="12">王五</option>
  <option value="13">黃六</option>
  <option value="14">錢七</option>
</select>

顯示效果如下:

當選項較少的時候,此種下拉列表自然夠用了,然而當選項特別多(比如超過100個)的時候,使用者要從其中選擇特定項可能需要從頭拉到尾,還需要肉眼match,不但工作量巨大,而且容易出錯,於是自然出現了可編輯+自動匹配的下拉列表型別的需求。

最簡單的可編輯下拉列表實現

H5標準中新提出了一個datalist標籤,使用datalist+input可很簡單地實現可編輯、智慧匹配的下拉框:

<input list="id_datalist">
<datalist id="id_datalist" name="staff">
  <option value="10">張三</option>
  <option value="11">李四</option>
  <option value="12">王五</option>
  <option value="13">黃六</option>
  <option value="14">錢七</option>
</datalist>

選擇顯示效果如下:

此下拉框支援人工輸入內容,並且會根據已輸入部分自動更新可匹配選項列表,直接使用input+datalist標籤實現,簡單易懂無需額外js邏輯程式碼,單從使用上已可謂接近完美。
然而美中不足的是,選中option後,在輸入框中預設顯示的就是option.value 的值,而非其對應innerText,這對於value與innerText取值不一樣的場景,極大地降低了選項的可讀性,如下:選擇王五之後,輸入框只顯示了12這個value,而沒有顯示王五這個innerText內容:

可編輯且預設顯示option.innerText的下拉列表實現

為了解決上面提到的input預設顯示option.value而非option.innerText的問題,找遍網上資料,目前發現暫時還是隻能通過額外新增一些js程式碼邏輯來解決,其基本思想是使用兩個input輸入框,一個負責顯示選項,另外一個負責實際的value儲存(

Show datalist labels but submit the actual value),使用者網頁實際只能看到負責顯示的input,而儲存實際value的input設定為type="hidden"隱藏掉,只有提交表單時會默默地提交到後端。
參考stackoverflow中Stephan Muller和cobbystreet兩位答主的答案,一個能區分不同value具有相同innerText內容選項的程式碼實現如下:

<script type="text/javascript">
	function checkSelectSet(e) {
		var input = e.target,
			list = input.getAttribute('list'),
			options = document.querySelectorAll('#' + list + ' option[value="'+input.value+'"]'),
			hiddenInput = document.getElementById(input.getAttribute('id').replace('-display', ''));

		if (options.length > 0) {
			  hiddenInput.value = input.value;
			  input.value = options[0].innerText;
		  }
	}

	function addDataListListener(eid) {
		document.querySelector('#'+eid).addEventListener('input', checkSelectSet)
	}
</script>
<input type="text" name="staff-display" id="id_staff-display" list="list__staff" value="-" oninput="addDataListListener('id_staff-display')">
<datalist id="list__staff">
  <option value="10">張三</option>
  <option value="11">李四</option>
  <option value="12">王五</option>
  <option value="13">黃六</option>
  <option value="14">錢七</option>
  <option value="15">錢七</option>
</datalist>
<input type="hidden" name="staff" value="" id="id_staff">

實現效果如下:

選定後效果:

轉載請註明出處,原文地址:https://www.cnblogs.com/AcAc-t/p/readable_editable_dropdown_list_by_input_datalist.html

參考:
Show datalist labels but submit the actual value: https://stackoverflow.com/questions/29882361/show-datalist-labels-but-submit-the-actual-value

簽名:擁抱開源,擁抱自由