HTML 요소없이 ng-repeat를 사용하는 방법
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>
업데이트 : 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>
AngularJS 1.2부터는 ng-repeat-start
정확히 요청하는 것을 지시하는 지시문 이 있습니다. 사용 방법에 대한 설명은 이 질문에 대한 답변 을 참조하십시오 .
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>
The important point: for tags used for ng-repeat-start
and ng-repeat-end
set ng-if="0"
, to let not be inserted in the page. In this way the inner content will be handled exactly as it is in knockoutjs (using commands in <!--...-->
), and there will be no garbage.
You might want to flatten the data within your controller:
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;
}
}
And then in the HTML:
<table>
<tbody>
<tr ng-repeat="item in flattened()"><td>{{item}}</td></tr>
</tbody>
</table>
The above is correct but for a more general answer it is not enough. I needed to nest ng-repeat, but stay on the same html level, meaning write the elements in the same parent. The tags array contain tag(s) that also have a tags array. It is actually a tree.
[{ name:'name1', tags: [
{ name: 'name1_1', tags: []},
{ name: 'name1_2', tags: []}
]},
{ name:'name2', tags: [
{ name: 'name2_1', tags: []},
{ name: 'name2_2', tags: []}
]}
]
So here is what I eventually did.
<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>
Note the ng-if="false" that hides the start and end divs.
It should print
name1,name1_1,name1_2,name2,name2_1,name2_2,
I would like to just comment, but my reputation is still lacking. So i'm adding another solution which solves the problem as well. I would really like to refute the statement made by @bmoeskau that solving this problem requires a 'hacky at best' solution, and since this came up recently in a discussion even though this post is 2 years old, i'd like to add my own two cents:
As @btford has pointed out, you seem to be trying to turn a recursive structure into a list, so you should flatten that structure into a list first. His solution does that, but there is an opinion that calling the function inside the template is inelegant. if that is true (honestly, i dont know) wouldnt that just require executing the function in the controller rather than the directive?
either way, your html requires a list, so the scope that renders it should have that list to work with. you simply have to flatten the structure inside your controller. once you have a $scope.rows array, you can generate the table with a single, simple ng-repeat. No hacking, no inelegance, simply the way it was designed to work.
Angulars directives aren't lacking functionality. They simply force you to write valid html. A colleague of mine had a similar issue, citing @bmoeskau in support of criticism over angulars templating/rendering features. When looking at the exact problem, it turned out he simply wanted to generate an open-tag, then a close tag somewhere else, etc.. just like in the good old days when we would concat our html from strings.. right? no.
as for flattening the structure into a list, here's another solution:
// 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']
this will work for any tree-like structure that has sub items. If you want the whole item instead of a property, you can shorten the flattening function even more.
hope that helps.
for a solution that really works
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>
add an angular.js directive
//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]);
}());
for a brief explanation,
ng-repeat binds itself to the <remove>
element and loops as it should, and because we have used ng-repeat-start / ng-repeat-end it loops a block of html not just an element.
then the custom remove directive places the <remove>
start and finish elements with <!--removed element-->
<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>
I think that this is valid :)
참고URL : https://stackoverflow.com/questions/11490968/how-to-use-ng-repeat-without-an-html-element
'Programming' 카테고리의 다른 글
Build.scala, % 및 %% 기호 의미 (0) | 2020.06.21 |
---|---|
너비 우선 검색을 재귀 적으로 수행 (0) | 2020.06.21 |
C #에서 간단한 프록시를 만드는 방법은 무엇입니까? (0) | 2020.06.21 |
datetime을 삽입하는 동안 문자열에서 날짜 및 / 또는 시간을 변환 할 때 변환에 실패했습니다 (0) | 2020.06.21 |
Java에서 .class는 무엇을 의미합니까? (0) | 2020.06.21 |