將AJAX取得的JSON資料回綁至FORM表單或HTML元素
雖然前端雙向綁定的Javascript框架已經非常成熟,但自己在使用上還是偏好採用自行設計並綁定,因為有許多商業邏輯的限制、自行包裝的元件等因素並不適用這種雙向綁定的框架,因此這篇文章試圖介紹一種我自己習慣的單向綁定方法。
JSON Data Binding 資料綁定
這篇文章示範的是我自己常使用的資料綁定方式,當AJAX自伺服器端取回JSON資料後,通常我們預期應該是Key、Value的資料格式,這時候若沒有框架幫忙,我們會需要很辛苦的一個一個把Value指派回去,這時候只要套用這個寫好的方法,它會自動以Key去現有的DOM尋訪「可能適用」的元素,並試圖將Value指派至該元素,若以一個大型的表單來說,這個舉動會節省掉非常多無謂的Coding時間。
此外,我採用的是jQuery框架來進行DOM操作,VanillaJS門派的人就請自行離開啦。
function JsonDataBinding(oData) {
let fnError = function (cTemp) {
console.log(`JsonDataBinding: ${cTemp}`);
};
$.each(oData, function (cKey, cValue) {
let oDom = "";
if (oDom.length === 0) { oDom = $(`input[name=${cKey}]`); }
if (oDom.length === 0) { oDom = $(`select[name=${cKey}]`); }
if (oDom.length === 0) { oDom = $(`textarea[name=${cKey}]`); }
if (oDom.length === 0) { oDom = $(`[name=${cKey}]`); }
if (oDom.length === 0) { oDom = $(`#${cKey}:not(.date)`); } //規避某些自製包裝元件,若不需要者可自行移除
if (oDom.length === 0) { fnError(`Can't find elements with Key: ${cKey}`); return; }
switch (oDom.prop("tagName")) {
case "INPUT":
switch (oDom.prop("type")) {
case "text":
case "number":
oDom.val(cValue);
break;
case "radio":
oDom.filter(`[value=${cValue}]`).attr("checked", cValue);
break;
case "checkbox":
if (typeof cValue === 'boolean')
{ oDom.attr("value", cValue).attr("checked", cValue); }
else if ($.isArray(cValue))
{
$.each(cValue, function (cIndex, cArrayValue) {
oDom.filter(`[value=${cArrayValue}]`).attr("checked", true);
});
}
else
{ oDom.filter(`[value=${cValue}]`).attr("checked", true); }
break;
case "date":
oDom.val(`${cValue.substring(0, 4)}-${cValue.substring(5, 7)}-${cValue.substring(8, 10)}`);
break;
default:
fnError(`Not implemented with INPUT element: ${oDom.prop("type")}`)
break;
}
break;
case "SELECT":
oDom.find(`option[value=${cValue}]`).attr("selected", true);
break;
case "TEXTAREA":
oDom.val(cValue);
break;
case "DIV":
case "P":
case "SPAN":
case "TD":
oDom.html(String(cValue).replace(new RegExp("\r?\n", "g"), "<br/>"));
break;
default:
fnError(`Not implement with HTML element: ${oDom.prop("tagName")}`);
break;
}
});
}
大致上的運行重點就是先去找FORM元素等級的物件,並以NAME屬性為先決條件,如果最後都找不到的話,才會以非FORM元素的NAME或ID再往下找,再沒有找到則會依據現行的狀況拋出錯誤資訊於console下,以利除錯。
驗證運作
首先取得下列JSON資料:
var oJSON = {
"cName": "王小明",
"bSex": true,
"iSalary": 12345,
"dBirthday": "2022/11/22",
"cInterest": "shopping",
"cLuckyNumber": [1, 3, 5],
"cAge": "21-30",
"cNote1": "AAA\nBBB\nCCC",
"cNote2": "DDD\nEEE\nFFF",
"cCanNotFind": "brabra..."
};
將JSON資料套用到下列HTML之中:
<html>
<body>
<p>表單元素:</p>
<form>
姓名:<input type="text" name="cName"><br>
<!--示範複選但用於單選結構-->
性別:<input type="checkbox" name="bSex">(打勾:男生;沒勾:女生)<br>
薪資:<input type="number" name="iSalary"><br>
生日:<input type="date" name="dBirthday"><br>
興趣:
<input type="radio" name="cInterest" value="travel">旅行
<input type="radio" name="cInterest" value="shopping">購物
<input type="radio" name="cInterest" value="sleep">睡覺<br>
<!--示範複選且用於多選結構-->
幸運數字:
<input type="checkbox" name="cLuckyNumber" value="1">1
<input type="checkbox" name="cLuckyNumber" value="2">2
<input type="checkbox" name="cLuckyNumber" value="3">3
<input type="checkbox" name="cLuckyNumber" value="4">4
<input type="checkbox" name="cLuckyNumber" value="5">5<br>
年齡區間:
<select name="cAge">
<option value="11-20">11-20</option>
<option value="21-30">21-30</option>
<option value="31-40">31-40</option>
</select><br>
備註:<textarea name="cNote1"></textarea>
</form>
<p>非表單元素:</p>
<div id="cNote2"></div>
<span id="cCanNotFind_NOooo"></span>
</body>
</html>
最後直接調用JsonDataBinding方法,就可以看到資料都自動綁定HTML元素啦!
$(function(){
JsonDataBinding(oJSON);
});
最後一個SPAN元素(cCanNotFind_NOooo)因為沒有辦法對齊至JSON的KeyName(cCanNotFind),所以執行後可以看到一行console.log訊息:
JsonDataBinding: Can't find elements with Key: cCanNotFind
另外要說明的是,這種自幹的簡易版單向綁定方法,向來都會因為自己專案當前的狀況而論定,功能性不可能涵蓋所有考量且面面俱到,故請依照自己的需求隨時增修為佳。