雙列表框(雙向選擇器)右側選中項需全部提交給後端,且必須保持用戶調整的顯示順序。隱藏 radio 方案因按 ID 排序導致順序錯亂;JS 預選中 selected 方案在頁面非正常離開(關閉標籤頁、瀏覽器崩潰、跳轉)時不可靠。
原則:不依賴 DOM selected 狀態,而是在 submit 事件中讀取右側 ListBox 的選項順序,構造隱藏字段或直接發送 AJAX。
<form id="mainForm" action="/submit" method="post">
<!-- 其他業務字段 -->
<select id="rightList" name="rightList" multiple size="10"></select>
<input type="hidden" name="orderedValues" id="orderedValues">
<button type="submit">提交</button>
</form>
<script>
document.getElementById('mainForm').addEventListener('submit', function(e) {
const select = document.getElementById('rightList');
const values = Array.from(select.options).map(opt => opt.value);
// 關鍵:生成同名隱藏字段,後端按數組接收
// 或用 JSON 序列化單字段
document.getElementById('orderedValues').value = JSON.stringify(values);
// 若後端要求同名多值:動態創建 input
// values.forEach(v => { const h = document.createElement('input'); h.type='hidden'; h.name='orderedValues'; h.value=v; this.appendChild(h); });
});
</script>
async function submitData() {
const select = document.getElementById('rightList');
const orderedValues = Array.from(select.options).map(opt => opt.value);
const formData = new FormData(document.getElementById('mainForm'));
formData.set('orderedValues', JSON.stringify(orderedValues)); // 覆蓋或追加
try {
const resp = await fetch('/submit', { method: 'POST', body: formData });
if (resp.ok) alert('保存成功');
} catch (err) { console.error(err); }
}
// 綁定按鈕點擊,阻止默認提交
document.getElementById('submitBtn').addEventListener('click', e => {
e.preventDefault();
submitData();
});
const rightItems = ref([])。rightItems.value,無需操作 DOM。selected 屬性。onsubmit 或 AJAX 發送前瞬間讀取數組生成提交負載。List orderedValues 或 String orderedValuesJson。window.onbeforeunload、onunload 等不可靠生命週期。// Spring Boot
@PostMapping("/submit")
public Result submit(@RequestParam("orderedValues") String orderedValuesJson) {
List ordered = JSON.parseArray(orderedValuesJson, String.class);
// 按 ordered 順序處理業務
return Result.ok();
}