SB_76 SB_76 - 7 months ago 41
Java Question

Iterate over an ArrayList< Map<String, String>> from a Java Bean using JSTL?

Having a bit of difficulty getting this sorted. In my JSP page, I have a table that displays x amount of rows with 3 columns. In my Java bean, I have this declared as:

private ArrayList<Map<String, String>> issueClient = new ArrayList<>();
private ArrayList<Map<String, String>> issueR2 = new ArrayList<>();


I get my values through MVC and place them into the Map using:

if (crs != null && crs.size() > 0) {
try {
while (crs.next()) {
HashMap<String, String> tmpPart = new HashMap<>();

tmpPart.put("part", crs.getString("part"));
tmpPart.put("type", crs.getString("part_type"));
tmpPart.put("id_issue", crs.getString("id_part"));
tmpPart.put("issue", crs.getString("part_name"));

repairPartAddNew.addIssueClientMap(tmpPart);
}
} catch (Exception e) {
....
}
} else {
....
}


repairPartAddNew is a reference to the Java Bean containing the ArrayList Map noted above. In my JSP, I have started to construct the following:

<c:if test="${repairPartAddNew.issueClient != null}">
<c:set var="loopValue" value="1" scope="page" />
<c:forEach var="issueClient" items="${repairPartAddNew.issueClient}" varStatus="loop">
<c:forEach var="map" items="${issueClient}">
<tr>
<td>
<form:select disabled="disabled" multiple="false" id="clientReportIssuePart${loopValue}" class="form-control input-sm" name="clientReportIssuePart" path="clientReportIssuePart" onchange="getPartSubtypes(this.value,$(this).parent().next().find('select').attr('id'));">
<form:option value="${map.value}">${map.value}</form:option>
<form:options items="${descriptionParts}" itemValue="value" itemLabel="name"/>
</form:select>
</td>
<td>
<form:select disabled="disabled" multiple="false" class="form-control input-sm" id="clientPartType${loopValue}" name="clientPartType" path="clientPartType" onchange="getRepairPartIssue(this.value,$(this).parent().next().find('select').attr('id'),$(this).parent().prev().find('select').val());">
<form:option value="${map.value}">${map.value}</form:option>
</form:select>
</td>
<td>
<form:select disabled="disabled" multiple="false" class="form-control input-sm" id="clientRepair${loopValue}" name="clientReportIssuePartId" path="clientReportIssuePartId">
</form:select>
</td>
</tr>
</c:forEach>
<c:set var="loopValue" value="${loopValue + 1}" scope="page"/>
</c:forEach>
</c:if>


I end up with various abominations in data structure, including the http://prnt.sc/azjlgp

It seems like iterating over the Array and Map is producing duplicate rows. In this example, there should only be 2 table rows.

Any help is greatly appreciated.

Answer

I'd recommend using an object to store all of your values instead of a HashMap. You can then store each row data in that object and store them all in an ArrayList. You should then be able to pull each value from the object as needed.

        <c:if test="${repairPartAddNew.clientReportIssuePart != null}">
                <c:set var="loopValue" value="1" scope="page" />
                <c:forEach var="issueClient" items="${repairPartAddNew.issueClientList}" varStatus="loop">
                        <tr>
                            <td>
                                <form:select disabled="disabled" multiple="false" id="clientReportIssuePart${loopValue}" class="form-control input-sm" name="clientReportIssuePart" path="clientReportIssuePart"
                                             onchange="getPartSubtypes(this.value,$(this).parent().next().find('select').attr('id'));">
                                    <form:option value="${issueClient.part}">${issueClient.part}</form:option>
                                    <form:options items="${descriptionParts}" itemValue="value" itemLabel="name"/>
                                </form:select>
                            </td>

                            <td>
                                <form:select disabled="disabled" multiple="false" class="form-control input-sm" id="clientPartType${loopValue}" name="clientPartType" path="clientPartType"
                                             onchange="getRepairPartIssue(this.value,$(this).parent().next().find('select').attr('id'),$(this).parent().prev().find('select').val());">
                                    <form:option value="${issueClient.type}">${issueClient.type}</form:option>
                                </form:select>
                            </td>

                            <td>
                                <form:select disabled="disabled" multiple="false" class="form-control input-sm" id="clientRepair${loopValue}" name="clientReportIssuePartId" path="clientReportIssuePartId">
                                    <form:option value="${issueClient.id_issue}">${issueClient.issue}</form:option>
                                </form:select>
                            </td>
                            <td class="text-center width-100">
                                <button type="button" id="deleteClientRowBtn" class="btn btn-outline btn-sm btn-dark"
                                        onclick="deleteRow(this, $(this).closest('table').attr('id'))">Delete Row
                                </button>
                            <td class="text-center width-100">
                                <button type="button" class="btn btn-outline btn-sm btn-dark"
                                        onclick="addTableRow('tableClientTemplate', $(this).closest('table').attr('id'))">Add Row
                                </button>
                            </td>
                        </tr>
                    <c:set var="loopValue" value="${loopValue + 1}" scope="page"/>
                </c:forEach>
            </c:if>

        </tbody>

Hope that helps.