JSP循环异常:遍历数组设置select的selected属性出错
问题分析与解决方案
嘿,这个问题其实很常见,我一眼就看出问题出在哪啦!
为什么会出现选项重复?
你嵌套了两层<c:forEach>循环:外层遍历所有国家,内层遍历需要选中的国家。这意味着每一个国家都会和选中列表里的每一个国家对比一次,每对比一次就输出一个<option>标签。举个例子:如果divisa.paises里有3个选中国家,那每个国家都会被输出3次——匹配时输出带selected的选项,不匹配时输出不带的,最终就导致了选项重复。
修正方案
我们只需要遍历一次全部国家列表,然后在每个选项里判断当前国家是否属于选中列表即可,不需要嵌套循环。这里提供两种常用的实现方式:
方式1:先预处理选中ID集合(效率更高)
先把需要选中的国家ID拼接成一个字符串,再用JSTL的fn:contains判断当前国家是否在选中列表里:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <!-- 先把选中的国家ID拼接成逗号分隔的字符串 --> <c:set var="selectedPaisIds" value="" /> <c:forEach items="${divisa.paises}" var="paisoption"> <c:set var="selectedPaisIds" value="${selectedPaisIds},${paisoption.idpais}" /> </c:forEach> <!-- 去掉开头多余的逗号 --> <c:set var="selectedPaisIds" value="${fn:substringAfter(selectedPaisIds, ',')}" /> <select multiple id="paisesSeleccionados" name="paisesSeleccionados"> <option value="" disabled>País</option> <c:forEach items="${listadoPaises}" var="pais"> <option value="${pais.idpais}" data-icon="${pageContext.request.contextPath}/resources/flags/${pais.siglas}.png" <c:if test="${fn:contains(selectedPaisIds, pais.idpais)}">selected</c:if> > ${pais.nombre} </option> </c:forEach> </select>
方式2:直接在循环内判断(代码更直观)
遍历每个国家时,检查当前国家是否在选中列表里,找到匹配后立即跳出内层循环,避免不必要的遍历:
<select multiple id="paisesSeleccionados" name="paisesSeleccionados"> <option value="" disabled>País</option> <c:forEach items="${listadoPaises}" var="pais"> <c:set var="isSelected" value="false" /> <!-- 检查当前国家是否在选中列表里 --> <c:forEach items="${divisa.paises}" var="paisoption"> <c:if test="${pais.idpais == paisoption.idpais}"> <c:set var="isSelected" value="true" /> <c:break /> <!-- 找到匹配就停止内层循环 --> </c:if> </c:forEach> <option value="${pais.idpais}" data-icon="${pageContext.request.contextPath}/resources/flags/${pais.siglas}.png" ${isSelected ? 'selected' : ''} > ${pais.nombre} </option> </c:forEach> </select>
两种方式都能解决选项重复的问题,同时正确设置selected属性,实现你想要的多选选中效果~
内容的提问来源于stack exchange,提问作者Nacho Martin
相关产品推荐
相关产品推荐

