解決Bootstrap custom-switch無法賦值、取值錯誤問題
今天在使用Bootstrap custom-switch客製化開關元件時,發現在UI層面上的操作並無法影響底層的實際賦值,導致最後Javascript取出時根本就沒有辦法拿到正確、表裡如一的資料,這篇文章就是在介紹如何改善這個問題。
討論並解決Bootstrap custom-control-input值表裡不一的問題
Step 1. 建立一個典型的Bootstrap開關元件
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="bIsEnabled">
<label class="custom-control-label increaseCheckbox" for="bIsEnabled">是否開啟?</label>
</div>
</div>
<style>
.increaseCheckbox {
line-height: 1.5;
margin-left: 1.4em;
transform: scale(1.2);
}
</style>
Step 2. 建立一個按鈕並調用jQuery去讀取這個元件的值,發現出現的是on/off值,以現在的狀況(HTML中根本沒有設定預設值)來說,alert上卻是顯示on。
$(function () {
$("#btn").click(function () {
alert($("#bIsEnabled").val());
});
});
Step 3. 一般來說資料送到後端都是要以boolean型態儲存,所以應該是true/false才對。但沒事,這個鍋不應該是Bootstrap背,這本來就是HTML的規範,只要稍微實作先賦予value屬性true/false就解決,例如:
<input type="checkbox" class="custom-control-input" id="bIsEnabled" value="false">
註:若嫌麻煩也可以透過jQuery在DocumentReady時期就覆寫掉,這樣你就可以不用補value在HTML上了。這類型的元素一多起來,甚至可以透過Selector一次性選取解決。
$("#bIsEnabled").attr("value", false);
Step 4. 這下alert回傳正確的false了,但是我們發現去點選UI的switch開關並不能如實的反應真正的true/false狀態,也就是說jQuery取到的value在此刻永遠為false。
Step 5. 按下F12切換到瀏覽器開發者模式,發現這顆input type="checkbox"元素,就算表面UI在那邊不斷切換,他在背景依然躺平連動都不動一下,這代表Bootstrap在後面並沒有幫我們實作真實數值或狀態的toggle,果然只負責到「表面的顯示」而已。
Step 6. 知道真相後只能再請jQuery好朋友出來幫忙,設定custom-control-input的監聽事件,如果有被點選異動就馬上去把應該賦予的內含值改掉。(這段程式碼比較消耗前端效能,也會因為應用的場域不同而迥異,請自行視需求變更)
$(".custom-control-input").on("change", function (e) {
$(this).attr("value", e.target.checked).attr("checked", e.target.checked);
});
透過瀏覽器開發者模式我們可以觀察背景的數值的確被賦予正確的HTML屬性了。
上面這張圖是開啟狀態背後的屬性值。
上面這張圖是關閉狀態背後的屬性值。
透過這樣的程式碼增補,可以讓FormData收集表單數值更加直觀便利,以上說明。
補充:HTML jQuery事件監聽的寫法
在早期WebForm的寫法中,我們會很常宣告了一堆ServerControl Buttons,然後透過單一方法來得知是按下哪顆按鈕,進而讓程式碼更精簡,例如:
void button_Click(object sender, EventArgs e)
{ var s = (sender as Button).Text; }
那麼,等效的程式碼在Javascript可以看待成:
$("button").on("click", function (e) {
var s = e.target.id;
});