#ids.seq 사용하기 ( feat. prev 와 next )
th:each 사용시 내부에서 ids.seq 를 사용하면 index(ID count) 처리를 할 수 있다. 이 때 index 는 1 부터 시작한다.
- prev
each 문에 의해 loop 를 돌 때마다 index 값은 1개씩 증가하는데, prev 는 바로 이전에 해당하는 index 값이 반환 됨을 알 수 있다.
이 때 주의 해야할 점은 객체를 사용하지 않으면 index 는 생성되지 않는다. 따라서 객체를 사용하지 않았는데 prev 를 쓴다면 다음과 같은 예외가 발생한다.
org.attoparser.ParseException: Cannot obtain previous ID count for ID
간단한 예제를 들어보자.
<li class="list-group-item" th:each="material : ${materials}">
<input type="checkbox" th:field="*{materialIds}" th:value="${material.id}" autocomplete="off">
<label class="btn" th:for="${#ids.prev('materialIds')}" th:text="${material.name}"></label>
</li>
위 코드에서 materialsId 라는 객체가 input 에서 먼저 사용되었기 때문에 #ids.prev('materialsIds') 의 결과는 materialsId1 을 반환한다.
따라서 결과는 다음과 같다.
<li class="list-group-item">
<input type="checkbox" value="1" autocomplete="off" id="materialIds1" name="materialIds">
<input type="hidden" name="_materialIds" value="on">
<label class="btn" for="materialIds1">진피</label>
</li>
여기서 <label> 과 <input> 의 선언순서가 바뀌었을 때 org.attoparser.ParseException: Cannot obtain previous ID count for ID 예외가 발생하는 것이다.
- next
next 는 이후의 시퀀스 값을 가져 온다. prev 와 다르게 다음 index 를 먼저 계산해서 부여하기 때문에 객체선언보다 먼저 쓸 수 있다.
다음 코드를 보자.
<li class="list-group-item" th:each="material : ${materials}">
<label class="btn" th:for="${#ids.next('materialIds')}" th:text="${material.name}"></label>
<input type="checkbox" th:field="*{materialIds}" th:value="${material.id}" autocomplete="off">
</li>
materialIds 보다 먼저 선언 되었음에도 불구하고 prev 처럼 오류가 발생하지 않는다.
결과를 보면 #ids.next('materialIds') 가 선언된 시점으로부터 다음 객체의 index 에 해당하는 값이 반환 되는 것을 볼 수 있다.
<li class="list-group-item">
<label class="btn" for="materialIds1">진피</label>
<input type="checkbox" value="1" autocomplete="off" id="materialIds1" name="materialIds">
<input type="hidden" name="_materialIds" value="on">
</li>
이해를 돕기 위해 한가지 예제를 더 작성해봤다.
만약 next 를 사용하는데 객체 뒤에 쓴다면 어떻게 될까?
<li class="list-group-item" th:each="material : ${materials}">
<input type="checkbox" th:field="*{materialIds}" th:value="${material.id}" autocomplete="off">
<label class="btn" th:for="${#ids.next('materialIds')}" th:text="${material.name}"></label>
</li>
간단하다. 다음 값인 materialsId2 가 반환된다.
<li class="list-group-item">
<input type="checkbox" value="1" autocomplete="off" id="materialIds1" name="materialIds">
<input type="hidden" name="_materialIds" value="on">
<label class="btn" for="materialIds2">진피</label>
</li>
일반적으로는 checkbox 와 Label 설정을할 때 많이 사용한다. prev 를 사용할 경우에는 label 을 기준으로 input 을 먼저, next 는 용input 을 나중에 둬서 편하게 사용할 수 있다.