首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JSP 模態對話框傳值實現:showModalDialog 父子頁面數據回填完整方案

     編輯:程式設計綜合問答

技術棧

  • JSP + Servlet + jQuery
  • window.showModalDialog (IE 專用,現代瀏覽器建議改用 window.open + postMessage)

核心邏輯


+------------------+     openwindow()      +------------------+
|    add.jsp       | ─────────────────────→ |   select.jsp     |
| (父頁面)         | ←──── 回填數據 ─────── | (子頁面/彈窗)   |
+------------------+    window.opener       +------------------+

add.jsp (父頁面)

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script>
function openSelectDialog() {
    // 使用 showModalDialog (僅 IE 支援)
    // 現代瀏覽器請改用 window.open + postMessage 方案
    var dialog = window.showModalDialog(
        '/jxw/xq.do?action=showTjList',
        window,  // 傳遞 window 對象給子頁面,子頁面可用 dialogArguments 獲取
        'dialogWidth:600px;dialogHeight:500px;status:no;scroll:yes;resizable:yes'
    );
    
    // showModalDialog 返回值方案 (子頁面 window.returnValue = ...)
    if (dialog) {
        $('#xqName').val(dialog.name);
        $('#xqId').val(dialog.id);
    }
}

// 現代瀏覽器兼容方案:window.open + postMessage
function openSelectDialogModern() {
    var popup = window.open('/jxw/xq.do?action=showTjList', '_blank', 'width=600,height=500');
    window.addEventListener('message', function(event) {
        if (event.origin !== location.origin) return; // 安全校驗
        if (event.data.type === 'SELECT_RESULT') {
            $('#xqName').val(event.data.name);
            $('#xqId').val(event.data.id);
            popup.close();
        }
    }, { once: true });
}
</script>
</head>
<body>
<form id="addForm" action="/xq.do?action=doAddxq" method="post">
    <table>
        <tr>
            <th><b>*</b>推薦企業:</th>
            <td>
                <input type="hidden" id="xqId" name="xqId" />
                <textarea readonly="readonly" id="xqName" name="xqName" class="cl_textarea_small" style="width:300px;height:60px;"></textarea>
                <input type="button" value="請選擇" onclick="openSelectDialogModern()" />
            </td>
        </tr>
    </table>
</form>
</body>
</html>

select.jsp (子頁面)

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script>
$(function() {
    // 綁定複選框事件:即時顯示已選名稱
    $('#dataTable').on('change', 'input[name="ifCheck"]', function() {
        var names = [], ids = [];
        $('#dataTable input[name="ifCheck"]:checked').each(function() {
            names.push($(this).closest('td').next().next().text().trim()); // 取企業名稱列
            ids.push(this.value);
        });
        $('#selectedNames').val(names.join(', '));
        $('#selectedIds').val(ids.join(','));
    });

    // 全選/反選
    $('#chkAll').on('change', function() {
        $('#dataTable input[name="ifCheck"]').prop('checked', this.checked).trigger('change');
    });
});

function confirmSelection() {
    var names = $('#selectedNames').val();
    var ids = $('#selectedIds').val();
    
    if (!ids) {
        alert('請至少選擇一條記錄');
        return;
    }

    // 方案一:showModalDialog 返回值 (IE)
    if (window.dialogArguments) {
        window.returnValue = { name: names, id: ids };
        window.close();
        return;
    }

    // 方案二:postMessage 回傳 (現代瀏覽器)
    if (window.opener) {
        window.opener.postMessage({
            type: 'SELECT_RESULT',
            name: names,
            id: ids
        }, location.origin);
        window.close();
    }
}

function cancelSelection() {
    window.close();
}
</script>
</head>
<body>
<h3>請選擇企業</h3>
<div>
    <label><input type="checkbox" id="chkAll" /> 全選</label>
    <input type="text" id="selectedNames" readonly style="width:400px;" placeholder="已選企業名稱" />
    <input type="hidden" id="selectedIds" />
</div>
<table id="dataTable" border="1" cellpadding="5" cellspacing="0" style="width:100%;">
    <thead>
        <tr><th><th>序號</th><th>企業名稱</th></tr>
    </thead>
    <tbody>
        <c:forEach items="${domain}" var="domain1" varStatus="status">
        <tr class="${status.count % 2 == 0 ? 'grid_dark' : ''}">
            <td><input type="checkbox" name="ifCheck" value="${domain1.id }" /></td>
            <td>${status.count }</td>
            <td>${domain1.qymc }</td>
        </tr>
        </c:forEach>
    </tbody>
</table>
<div style="margin-top:10px;text-align:right;">
    <input type="button" value="確定" onclick="confirmSelection()" />
    <input type="button" value="關閉" onclick="cancelSelection()" />
</div>
</body>
</html>

Action 層實現 (Struts 1 風格)

public ActionForward showTjList(ActionMapping mapping, ActionForm form,
                                HttpServletRequest request, HttpServletResponse response) {
    List list = enterpriseService.findAll();
    request.setAttribute("domain", list);
    return mapping.findForward("selectPage"); // 對應 select.jsp
}

關鍵點對比

方案showModalDialog (IE)window.open + postMessage (現代)
阻塞父頁面是否 (非模態)
返回值window.returnValuepostMessage
跨域支援否是 (需 origin 校驗)
瀏覽器支援僅 IE/Edge 舊版所有現代瀏覽器
推薦程度❌ 棄用✅ 標準

避坑指南

  • ❌ 不要用 document.all (IE 專有,已廢棄)
  • ✅ 使用 document.getElementById / jQuery
  • ✅ 子頁面表單 action 不需指向父頁面,純前端交互
  • ✅ 複選框 value 存 ID,顯示列存名稱,JS 取值更簡單
  • ✅ 現代專案請直接使用 window.open + postMessage 方案

此方案兼容新舊瀏覽器,採用標準 postMessage 機制,安全且可維護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved