AngularJS 형제 요소에 ng-repeat 사용하기

ng-repeat를 사용할 때 같은 레벨의 형제 요소들을 반복해야 하는 경우가 있습니다. ng-repeat-start와 ng-repeat-end를 활용하는 방법입니다.

1. 문제 상황

<!-- 원하는 결과 -->
<dt>제목1</dt>
<dd>내용1</dd>
<dt>제목2</dt>
<dd>내용2</dd>

<!-- 일반 ng-repeat로는 불가능 -->
<div ng-repeat="item in items">
    <dt>{{item.title}}</dt>
    <dd>{{item.content}}</dd>
</div>
<!-- 결과: <div>로 감싸짐 -->

2. ng-repeat-start / ng-repeat-end

<dl>
    <dt ng-repeat-start="item in items">{{item.title}}</dt>
    <dd ng-repeat-end>{{item.content}}</dd>
</dl>

<!-- 결과 -->
<dl>
    <dt>제목1</dt>
    <dd>내용1</dd>
    <dt>제목2</dt>
    <dd>내용2</dd>
</dl>

3. 테이블 행 그룹

<table>
    <tr ng-repeat-start="user in users">
        <td>{{user.name}}</td>
        <td>{{user.email}}</td>
    </tr>
    <tr ng-repeat-end>
        <td colspan="2">{{user.bio}}</td>
    </tr>
</table>

<!-- 결과: 사용자당 2개 행 생성 -->

4. 여러 형제 요소

<!-- 3개 이상의 형제 요소도 가능 -->
<div ng-repeat-start="section in sections">
    <h2>{{section.title}}</h2>
</div>
<p>{{section.intro}}</p>
<ul>
    <li ng-repeat="item in section.items">{{item}}</li>
</ul>
<hr ng-repeat-end>

5. 조건부 형제 요소

<dt ng-repeat-start="item in items">{{item.title}}</dt>
<dd ng-if="item.hasDetail">{{item.detail}}</dd>
<dd ng-if="!item.hasDetail" ng-repeat-end>상세정보 없음</dd>

6. 대안: ng-include

<!-- 템플릿 분리 -->
<script type="text/ng-template" id="item-template">
    <dt>{{item.title}}</dt>
    <dd>{{item.content}}</dd>
</script>

<dl>
    <ng-include ng-repeat="item in items" 
                src="item-template"></ng-include>
</dl>

7. 성능 최적화

<!-- track by로 성능 향상 -->
<dt ng-repeat-start="item in items track by item.id">
    {{item.title}}
</dt>
<dd ng-repeat-end>{{item.content}}</dd>

일반 ng-repeat vs ng-repeat-start 비교

구분ng-repeatng-repeat-start/end
래퍼 요소필요불필요
형제 요소불가가능
복잡도간단약간 복잡
사용 사례일반 목록dl, 복합 테이블

주의사항

  • ng-repeat-start와 ng-repeat-end는 반드시 쌍으로 사용
  • 중첩 ng-repeat와 함께 사용 시 변수 충돌 주의
  • Angular 1.2 이상에서 지원