HTML 요소없이 ng-repeat를 사용하는 방법


142

ng-repeat배열의 모든 요소를 ​​나열 하려면 (AngularJS에서) 사용해야 합니다.

문제는 배열의 각 요소가 테이블의 1, 2 또는 3 행으로 변환된다는 것입니다.

ng-repeat사이에 유형의 반복 요소가 허용되지 않으므로 요소에 사용되는 경우 유효한 HTML을 만들 수 없습니다 .<tbody><tr>

예를 들어, ng-repeat on을 사용하면 다음과 같은 결과가 나타납니다 <span>.

<table>
  <tbody>
    <span>
      <tr>...</tr>
    </span>
    <span>
      <tr>...</tr>
      <tr>...</tr>
      <tr>...</tr>
    </span>
    <span>
      <tr>...</tr>
      <tr>...</tr>
    </span>
  </tbody>
</table>          

어떤 HTML이 유효하지 않습니다.

그러나 내가 생성 해야하는 것은 다음과 같습니다.

<table>
  <tbody>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
    <tr>...</tr>
  </tbody>
</table>          

여기서 첫 번째 행은 첫 번째 배열 요소에 의해 생성되고 다음 행은 두 번째 배열과 다섯 번째 및 여섯 번째 배열 요소에 의해 생성됩니다.

ng-repeat를 바인딩하는 동안 HTML 요소가 렌더링되는 동안 '사라지는'방법을 어떻게 사용합니까?

아니면 이것에 대한 또 다른 해결책이 있습니까?


설명 : 생성 된 구조는 다음과 같아야합니다. 각 배열 요소는 테이블의 1-3 행 사이를 생성 할 수 있습니다. 답은 배열 요소 당 0-n 개의 행을 이상적으로 지원해야합니다.

<table>
  <tbody>
    <!-- array element 0 -->
    <tr>
      <td>One row item</td>
    </tr>
    <!-- array element 1 -->
    <tr>
      <td>Three row item</td>
    </tr>
    <tr>
      <td>Some product details</td>
    </tr>
    <tr>
      <td>Customer ratings</td>
    </tr>
    <!-- array element 2 -->
    <tr>
      <td>Two row item</td>
    </tr>
    <tr>
      <td>Full description</td>
    </tr>
  </tbody>
</table>          

"replace : true"를 사용해야합니까? 이것을보십시오 : stackoverflow.com/questions/11426114/…

또한 tr 자체에서 ng-repeat를 사용할 수없는 이유는 무엇입니까?

2
@Tommy, "배열의 각 요소는 테이블의 1, 2 또는 3 개의 행으로 변환됩니다". ng-repeat를 사용하면 tr내가 이해하는 한 배열 요소 당 하나의 행을 얻습니다.
fadedbee

1
알 겠어. 리피터에서 사용하기 전에 모델을 평평하게 할 수 있습니까?

@ 토미. tr하나의 배열 요소에 의해 생성되는 1-3 은 동일한 구조를 갖지 않습니다.
fadedbee

답변:


66

업데이트 : Angular 1.2 이상을 사용하는 경우 ng-repeat-start를 사용하십시오 . @jmagnusson의 답변을 참조하십시오.

그렇지 않으면 ng-repeat를 tbody에 넣는 것은 어떻습니까? (AFAIK, 단일 테이블에 여러 <tbody>가 있으면 괜찮습니다.)

<tbody ng-repeat="row in array">
  <tr ng-repeat="item in row">
     <td>{{item}}</td>
  </tr>
</tbody>

62
이것이 기술적으로 효과가있을 수 있지만,이 일반적인 유스 케이스에 대한 답변은 임의의 (그렇지 않으면 불필요한) 마크 업을 삽입해야한다는 것이 매우 실망 스럽습니다. 동일한 문제가 있습니다 (행 그룹 반복-하나 이상의 하위 TR을 가진 하나의 헤더 TR, 그룹으로 반복). 다른 템플릿 엔진과 사소한, Angular와는 잘 어울립니다.
Brian Moeskau 2016 년

1
동의했다. DT + DD 요소를 반복하려고합니다. 잘못된 줄 바꿈 요소를 추가하지 않고는 그렇게 할 수 없습니다
David Lin

2
@DavidLin, Angular v1.2에서 (나올 때마다) dt 및 dd와 같은 여러 요소를 반복 할 수 있습니다. youtube.com/watch?v=W13qDdJDHp8&t=17m28s
Mark Rajcok

:이 컨테이너가 제어 흐름 구문에서 사용 KnockoutJS 매끄럽게 처리 knockoutjs.com/documentation/foreach-binding.html를 . Angular가 곧 비슷한 것을 할 수 있기를 바랍니다.
Cory House

3
이 답변은 구식입니다. 대신 ng-repeat-start를 사용하십시오
iwein

73

AngularJS 1.2부터는 ng-repeat-start정확히 요청하는 것을 지시하는 지시문 이 있습니다. 사용 방법에 대한 설명은 이 질문에 대한 답변 참조하십시오 .


Angular가 따라 잡았습니다. 이것은 이제 올바른 해결책입니다.
iwein

33

ng> 1.2를 사용하는 경우 다음은 ng-repeat-start/end불필요한 태그를 생성하지 않고 사용하는 예입니다 .

<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <script>
      angular.module('mApp', []);
    </script>
  </head>
  <body ng-app="mApp">
    <table border="1" width="100%">
      <tr ng-if="0" ng-repeat-start="elem in [{k: 'A', v: ['a1','a2']}, {k: 'B', v: ['b1']}, {k: 'C', v: ['c1','c2','c3']}]"></tr>

      <tr>
        <td rowspan="{{elem.v.length}}">{{elem.k}}</td>
        <td>{{elem.v[0]}}</td>
      </tr>
      <tr ng-repeat="v in elem.v" ng-if="!$first">
        <td>{{v}}</td>
      </tr>

      <tr ng-if="0" ng-repeat-end></tr>
    </table>
  </body>
</html>

중요한 점은 : 사용 태그 ng-repeat-startng-repeat-end설정 ng-if="0"페이지에 삽입 할 수 없습니다 수 있도록. 이러한 방식으로 내부 컨텐츠는 knockoutjs와 동일한 방식으로 처리되며 (의 명령 사용 <!--...-->) 가비지가 없습니다.


ng-if = "0"을 설정하면 일치하는 ng-repeat-end를 찾을 수 없다는 오류가 발생합니다.
vikky MCTS

19

컨트롤러 내에서 데이터를 평평하게 할 수 있습니다.

function MyCtrl ($scope) {
  $scope.myData = [[1,2,3], [4,5,6], [7,8,9]];
  $scope.flattened = function () {
    var flat = [];
    $scope.myData.forEach(function (item) {
      flat.concat(item);
    }
    return flat;
  }
}

그리고 HTML에서 :

<table>
  <tbody>
    <tr ng-repeat="item in flattened()"><td>{{item}}</td></tr>
  </tbody>
</table>

1
아닙니다. ngRepeat 표현식 안에서 함수를 호출하는 것은 절대 권장하지 않습니다
Nik

! 내 경우, 나는 각 요소의 인덱스에 대한 구분 기호를 추가 할 수 = 0을 필요 않았다 ng-repeat-start, ng-repeat-end솔루션으로 반복에게 새로운 VAR 각 요소 전에이 분리 객체를 추가하는 추가 변수를 만들 수 있었고, 그래서 내 디자인을 휴식 : <div class="c477_group"> <div class="c477_group_item" ng-repeat="item in itemsWithSeparator" ng-switch="item.id" ng-class="{'-divider' : item.id == 'SEPARATOR'}"> <div class="c478" ng-switch-when="FAS"/> <div class="c478" ng-switch-when="SEPARATOR" /> <div class="c479" ng-switch-default /> </div> </div>
hermeslm를

6

위의 내용은 정확하지만 더 일반적인 대답으로는 충분하지 않습니다. ng-repeat를 중첩해야했지만 동일한 html 수준을 유지하여 동일한 부모에 요소를 작성해야합니다. 태그 배열에는 태그 배열도있는 태그가 포함됩니다. 실제로 나무입니다.

[{ name:'name1', tags: [
  { name: 'name1_1', tags: []},
  { name: 'name1_2', tags: []}
  ]},
 { name:'name2', tags: [
  { name: 'name2_1', tags: []},
  { name: 'name2_2', tags: []}
  ]}
]

여기에 내가 한 일이 있습니다.

<div ng-repeat-start="tag1 in tags" ng-if="false"></div>
    {{tag1}},
  <div ng-repeat-start="tag2 in tag1.tags" ng-if="false"></div>
    {{tag2}},
  <div ng-repeat-end ng-if="false"></div>
<div ng-repeat-end ng-if="false"></div>

시작 및 끝 div를 숨기는 ng-if = "false"에 유의하십시오.

인쇄해야합니다

name1, name1_1, name1_2, name2, name2_1, name2_2,


1

나는 단지 의견을 말하고 싶지만 내 명성은 여전히 ​​부족합니다. 그래서 문제를 해결하는 다른 솔루션을 추가하고 있습니다. 나는이 문제를 해결하기 위해 '최고의 해킹'솔루션이 필요하다는 @bmoeskau의 진술을 정말로 반박하고 싶습니다.이 게시물이 2 세인데도 최근 토론에서 나왔기 때문에 내 것을 추가하고 싶습니다. 2 센트를 소유하십시오 :

@btford가 지적했듯이 재귀 구조를 목록으로 바꾸려고하는 것처럼 보이므로 먼저 해당 구조를 목록으로 평면화해야합니다. 그의 해결책은 그렇게하지만 템플릿 내에서 함수를 호출하는 것은 우아하지 않다는 의견이 있습니다. 그것이 사실이라면 (정직하게, 나는 모른다) 지시어가 아닌 컨트롤러에서 함수를 실행해야한다고 생각하지 않습니까?

어느 쪽이든, HTML에는 목록이 필요하므로 렌더링하는 범위에는 해당 목록이 있어야합니다. 컨트롤러 내부의 구조를 평평하게하면됩니다. $ scope.rows 배열이 있으면 간단한 단일 ng-repeat로 테이블을 생성 할 수 있습니다. 해킹, 우아함, 단순히 작동하도록 설계된 방식이 없습니다.

각도 지시문에는 기능이 부족하지 않습니다. 그들은 단지 당신이 유효한 HTML을 작성하도록 강요합니다. 내 동료도 비슷한 문제를 겪었고 @bmoeskau가 각도 템플릿 / 렌더링 기능에 대한 비판을 지원한다고 언급했습니다. 정확한 문제를 볼 때, 그는 단순히 html을 문자열에서 연결할 때와 마찬가지로 오픈 태그를 생성 한 다음 다른 곳에서 가까운 태그 등을 생성하고 싶었습니다. 아니.

구조를 목록으로 병합하는 것과 관련하여 다른 해결책이 있습니다.

// assume the following structure
var structure = [
    {
        name: 'item1', subitems: [
            {
                name: 'item2', subitems: [
                ],
            }
        ],
    }
];
var flattened = structure.reduce((function(prop,resultprop){
    var f = function(p,c,i,a){
        p.push(c[resultprop]);
        if (c[prop] && c[prop].length > 0 )
          p = c[prop].reduce(f,p);
        return p;
    }
    return f;
})('subitems','name'),[]);

// flattened now is a list: ['item1', 'item2']

이것은 하위 항목이있는 모든 트리와 같은 구조에서 작동합니다. 속성 대신 전체 항목을 원하면 병합 기능을 훨씬 더 단축 할 수 있습니다.

도움이 되길 바랍니다.


좋은데 그것은 직접적으로 도움이되지는 않았지만 다른 해결책에 대한 내 마음을 열었습니다. 고마워요!
Marian Zburlea 16:30에

0

실제로 작동하는 솔루션

html

<remove  ng-repeat-start="itemGroup in Groups" ></remove>
   html stuff in here including inner repeating loops if you want
<remove  ng-repeat-end></remove>

angular.js 지시문 추가

//remove directive
(function(){
    var remove = function(){

        return {    
            restrict: "E",
            replace: true,
            link: function(scope, element, attrs, controller){
                element.replaceWith('<!--removed element-->');
            }
        };

    };
    var module = angular.module("app" );
    module.directive('remove', [remove]);
}());

간단한 설명을 위해

ng-repeat는 <remove>요소에 바인딩되고 필요한 대로 반복되며, ng-repeat-start / ng-repeat-end를 사용했기 때문에 요소가 아닌 html 블록을 반복합니다.

그런 다음 사용자 지정 remove 지시문은 <remove>시작 및 종료 요소를<!--removed element-->


-2
<table>
  <tbody>
    <tr><td>{{data[0].foo}}</td></tr>
    <tr ng-repeat="d in data[1]"><td>{{d.bar}}</td></tr>
    <tr ng-repeat="d in data[2]"><td>{{d.lol}}</td></tr>
  </tbody>
</table>

나는 이것이 유효하다고 생각합니다 :)


이것이 작동하는 동안 배열에 세 개의 요소가있는 경우에만 작동합니다.
btford

배열이 빈 배열 인 경우에도 배열에 3 개의 요소가 있는지 확인하십시오 (빈 배열이있는 반복은 아무 것도 렌더링하지 않음).
레난 토말 페르난데스

7
내 요점은 OP가 아마도 배열의 다양한 수의 항목에 작동하는 솔루션을 원한다는 것입니다. 템플릿에 "이 배열에는 세 개의 항목이 있어야합니다"하드 코딩이 좋지 않은 솔루션이라고 가정합니다.
btford

그의 질문에 대한 마지막 의견에서 그는 요소가 동일한 구조를 가지지 않으므로 각 구조를 하드 코딩하는 것이 불가피하다고 말합니다.
Renan Tomal Fernandes
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.