Как разбить и отобразить один ArrayList в несколько столбцов таблицы

У меня есть сервлет, который загружает файл свойств и содержит список из 100 имен тестовых случаев в объект ArrayList. После загрузки сервлет перенаправляется на JSP, который отображает список в таблице. Список длинный, поэтому я хотел бы какой-нибудь элегантный способ отобразить его в таблице, чтобы он разбивался, например, на три или четыре столбца в JSP.

Сейчас я разбиваю список на три подсписка в сервлете:

//load properties
Properties props = new Properties();
        ArrayList<String> tests = new ArrayList<String>();
        props.load(getServletContext().getResourceAsStream("/WEB-INF/sailcertifier.properties"));
        Pattern pattern = Pattern.compile("[A-Z]{3}-[0-9]{2}");     
        for (Enumeration<Object> e = props.keys(); e.hasMoreElements();) {
            String key = (String) e.nextElement();
            Matcher m = pattern.matcher(key);
            if (m.find())
                tests.add(key);
        }
        Collections.sort(tests, new TestOrderComparator());
        confBean.setPossibleTests(tests.toArray(new String[tests.size()]));
        int third = tests.size() / 3;
        List<String> testSubset1 = tests.subList(0, third);
        List<String> testSubset2 = tests.subList(third, third * 2);
        List<String> testSubset3 = tests.subList(third * 2, tests.size());
        //store the bean as a request attribute
        request.setAttribute("testSet1", testSubset1.toArray(new String[testSubset1.size()]));
        request.setAttribute("testSet2", testSubset2.toArray(new String[testSubset2.size()]));
        request.setAttribute("testSet3", testSubset3.toArray(new String[testSubset3.size()]));
        request.setAttribute("testsConf", confBean);
        request.setAttribute("certProps", props);
        //forward to tests selection page
        String url = "/sailcertifier/jsp/testsSelection.jsp";
        RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(url);
        response.setContentType("application/javascript");
        try {
            dispatcher.forward(request, response);
        } catch (ServletException e) {
            e.printStackTrace();
        }

В JSP я перебираю подсписки следующим образом (добавляя некоторые элементы html для каждого случая):

    <table>
        <tr>
            <td style="width: 33%">
                <table>
                    <tr>
                        <td>
                            <c:forEach var="testName" items="${testSet1}">
                                <tr>
                                    <td><label for="${testName}" id=${testName}Label>${testName}</label></td>
                                    <td><input id=${testName} type="checkbox" value=${testName} name="selTest"></input></td>
                                    <td><input id=${testName}Run type="button" value="Run Test" name="runButtons" /></td>
                                    <td><input id=${testName}ManPass type="button" value="Manual Pass" name="manPassButtons"/></td>
                                    <td><div id=${testName}Status style="width:100px"></td>
                                    <td></td>
                                    <td></td>
                                </tr>
                            </c:forEach>
                            <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
                        </td>
                    </tr>
                </table>
            </td>
            <td style="width: 33%">
                <table>
                    <tr>
                        <td>
                            <c:forEach var="testName" items="${testSet2}">
                                <tr>
                                    <td><label for="${testName}" id=${testName}Label>${testName}</label></td>
                                    <td><input id=${testName} type="checkbox" value=${testName} name="selTest"></input></td>
                                    <td><input id=${testName}Run type="button" value="Run Test" name="runButtons" /></td>
                                    <td><input id=${testName}ManPass type="button" value="Manual Pass" name="manPassButtons"/></td>
                                    <td><div id=${testName}Status style="width:100px"></td>
                                    <td></td>
                                    <td></td>
                                </tr>
                            </c:forEach>
                            <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
                        </td>
                    </tr>
                </table>
            </td>
            <td style="width: 33%">
                <table>
                    <tr>
                        <td>
                            <c:forEach var="testName" items="${testSet3}">
                                <tr>
                                    <td><label for="${testName}" id=${testName}Label>${testName}</label></td>
                                    <td><input id=${testName} type="checkbox" value=${testName} name="selTest"></input></td>
                                    <td><input id=${testName}Run type="button" value="Run Test" name="runButtons" /></td>
                                    <td><input id=${testName}ManPass type="button" value="Manual Pass" name="manPassButtons"/></td>
                                    <td><div id=${testName}Status style="width:100px"></td>
                                    <td></td>
                                </tr>
                            </c:forEach>
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>

Я признаю, что использование трех циклов JSTL for довольно уродливо (еще не понял, как использовать полный исходный список). Есть ли более чистый способ справиться с этим, используя какой-нибудь плагин jquery (например, плагин сетки jquery) или другой библиотеку (displaytag?) для равномерного разбиения на строки?


person Bizmarck    schedule 21.03.2013    source источник


Ответы (2)


Напечатайте <tr>, затем проведите цикл по списку массивов, затем напечатайте каждый элемент в <td> и напечатайте </tr><tr> через каждые n элементов, затем завершите цикл по списку массивов и, наконец, напечатайте </tr> после этого.

Например. новая строка каждый 3-й элемент:

<table>
    <tr>
        <c:forEach items="${items}" var="item" varStatus="loop">
            <c:if test="${not loop.first and loop.index % 3 == 0}">
                </tr><tr>
            </c:if>
            <td>${item}</td>
        </c:forEach>
    </tr>
</table>

${loop.index} возвращает индекс текущей итерации. % 3 будет возвращать 0 только в том случае, если оно делится на 3 без остатка (таким образом, когда индекс равен 0, 3, 6, 9, 12 и т. д.).

person BalusC    schedule 21.03.2013

я не уверен, что понял ваш запрос, но предположим, что у вас есть массив из 100 элементов, и вы хотите, чтобы 3 столбца отображали их, поэтому вы можете использовать свойство "float" для достижения этого: просто создайте div нужной вам ширины и перебирать массивы, создавая внутренние элементы div шириной/3:

     <div style="width:600px;margin:auto;">
          <c:forEach var="testName" items="${testSet}">
              <div style="float:left;width:200px;">whatever you want to do with ${testName}</div>
          </c:forEach>
     </div>
person matteosilv    schedule 21.03.2013