Nested ng-repeat-start / ng-repeat-end - javascript

ng-repeat-start / ng-repeat-end are used for looping through data without rendering parent element [Portal to Docs]. In my case, I want to display data in nested ng-repeat-start / ng-repeat-end blocks without extra elements.
I've tried to put two ng-repeat-start directives into the same element but it fails to display correctly. I somehow figured out a workaround as displayed below [Portal to Demo]. Any better solution for case like this?
data
[{
name: 'Chapter 1',
sections: [{
name: '1-1',
words: 1024
}, {
name: '1-2',
words: 512
}]
}, {
name: 'Chapter 2',
sections: [{
name: '2-1',
words: 2048
}, {
name: '2-2',
words: 256
}]
}]
html
<tr class="tr-for" ng-repeat-start="chapter in main.book"></tr>
<tr ng-repeat-start="section in chapter.sections" ng-repeat-end>
<td>{{chapter.name}}</td>
<td>{{section.name}}</td>
<td>{{section.words}}</td>
</tr>
<tr class="tr-end" ng-repeat-end></tr>
css
tr.tr-for,
tr.tr-end {
display: none;
}

Your internal ng-repeat should be the regular ngRepeat:
<tr class="tr-for" ng-repeat-start="chapter in main.book"></tr>
<tr ng-repeat="section in chapter.sections">
<td>{{chapter.name}}</td>
<td>{{section.name}}</td>
<td>{{section.words}}</td>
</tr>
<tr class="tr-end" ng-repeat-end></tr>
Update
Try use the first ngRepeat inside of tbody tag:
<tbody ng-repeat="chapter in main.book">
<tr ng-repeat-start="section in chapter.sections" ng-repeat-end>
<td>{{chapter.name}}</td>
<td>{{section.name}}</td>
<td>{{section.words}}</td>
</tr>
</tbody>

Related

Ng-repeat within an ng-repeat-start

My data:
$scope.members = [
{
projects: [...]
},
{
projects: [...]
}, ...
] // $scope.members.length == 15
My code:
<tr>
<th ng-repeat-start="member in members" ng-repeat="project in member.projects" ng-repeat-end ng-if="member.projects" >
{{project.name}}
</th >
</tr>
No element is generated. I checked the Elements in Chrome developer tool, and I found these in the <tr> tag comments like this:
<!-- ngRepeat: member in members -->
<!-- ngRepeat: member in members -->
<!-- end ngRepeat: member in members --> (x30)
I also tried this:
<tr ng-repeat-start="member in members">
<th ng-repeat="project in member.projects" ng-repeat-end ng-if="member.projects" >
{{project.name}}
</th >
</tr>
But then I have the error: Unterminated attribute, found 'ng-repeat-start' but no matching 'ng-repeat-end' found.
Does anyone have an idea? Thanks in advance.
Updated answer:
Get only the 'projects' arrays into a new array, like so:
$scope.projectsOnly = [];//empty array
$scope.members.forEach(function(item){
$scope.projectsOnly.push(item.projects);
})
and then loop only into that array, like so:
<tr>
<th ng-repeat="project in projectsOnly " >
{{project.name}}
</th >
</tr>
Hope helps, good luck.
You should simply do this with nested ng-repeat
<tr ng-repeat="member in members">
<th ng-repeat="project in member.projects" ng-if="member.projects">
{{project.get('name')}}
</th>
</tr>
you don't need the ng-if, and you shouldn't separate the ng-repeat start/end. Just use two ng-repeats, one inside the other:
<div ng-app="app">
<table ng-controller="TestController">
<tr ng-repeat="member in members">
<th ng-repeat="project in member.projects">
{{project.name}}
</th>
</tr>
</table>
</div>
and your controller can look like this:
var app = angular.module('app', []);
app.controller('TestController', function($scope) {
$scope.members = [{
projects: [{
name: '1'
}, {
name: '2'
}]
}, {
projects: [{
name: '3'
}, {
name: '4'
}]
}];
});

How to list parent child categories if parent child div is not inside one another?

I want to list categories and sub categories but problem is parent categories div is different and child div is different that is child div is not inside parent div so i am not getting how to list parent - child categories.
This is my code:
<!-- Parent Div Section -->
<div ng-repeat="item in MyData">
<table >
<tr>
<td >{{ item.parentCategoryName }}</td>
</tr>
</table>
</div>
<!-- Child Categories Div Section -->
<div>
<table >
<tr>
<td >{{ item.ChildCategoryName }}</td>
</tr>
</table>
</div>
Json Structure:
[
{
"parentCategoryName": "Electronics",
"SubCategories": [
{
"ChildCategoryName": "Mobile",
},
{
"ChildCategoryName": "TV",
},
{
"ChildCategoryName": "Ac",
}
]
},
{
"parentCategoryName": "Sports",
"SubCategories": [
{
"ChildCategoryName": "Shoes",
},
{
"ChildCategoryName": "Bike",
},
{
"ChildCategoryName": "Bags",
}
]
}
]
Expected output:
Note:Although it seems like both parent child div are same but there are lots of codes which i havent shown for better understanding that is why both div are in different section.So i cant change that because above design will render same output as shown in expected output.
You can use ng-repeat-start and ng-repeat-end. See the code below
<table>
<tr ng-repeat-start="item in MyData">
<td>{{item.parentCategoryName}}</td>
</tr>
<tr ng-repeat-end>
<td> </td>
<td colspan="2">
<table>
<tr ng-repeat="subCategory in item.SubCategories">
<td>{{subCategory.ChildCategoryName}}</td>
</tr>
</table>
</td>
</tr>
</table>
Rest you can alter according you. Hope it helps.

AngularJS - Trouble with ng-repeat

Here's the data I'm working with:
$scope.products = [
{
'id': 643,
'name': 'Product Name',
'applications': [
{
'id': 100,
'name': 'Adobe After Effects CC (2014)',
'gfx': [
{
'id': 514,
'name': 'Graphics AE Test 1'
}
]
},
{
'id': 101,
'name': 'Adobe Premiere Pro CC (2014)',
'gfx': [
{
'id': 514,
'name': 'Graphics AP Test 1'
},
{
'id': 512,
'name': 'Graphics AP Test 2'
}
]
}
]
}
];
What i'm trying to do is loop through all of the graphics card for a specific application. You choose the application via a dropdown, and I have the selected application in a variable {{ scope.selectedApplication }}. So with that, here's what I have tried:
<tr data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<td>{{ driver.gfx[$index].name }}</td>
</tr>
So this is somewhat working, just not exactly how I want. The filter is filtering it down to the correct application, which works fine. The problem I am having is that driver.gfx[$index].name is only showing the first result. Since I am looping through applications instead of gfx, the $index isn't going to work for me.
How can I loop through the graphics cards after my initial ng-repeat? It seems like I need two statements, but how would that work?
Am I going about this the wrong way?
you can have nested hg-repeat if you like to have a nested table.
<tr data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<td>
<table>
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
</table>
</td>
</tr>
if you want to have single denormalized table, one option would be to create a function that does the denormalization and then use result of that function in a normal hg-repeat.
The other option would be having multiple tbody. so your outer loop occurs on tbody and inner loop on row
<tbody data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
</tbody>
and finally you can have some rows that either style them as separators or just hide them by CSS and use ng-repeat-start and hg-repeat-end like this
<table>
<tr class="separator" data-ng-repeat-start="driver in result.applications | filter: { name: selectedApplication } track by $index"><td></td></tr>
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
<tr class="seperator" ng-repeat-end><td></td></tr>
</table>
You need another ng-repeat that loops through each gfx.
<td>
<ul>
<li ng-repeat="gfx in driver.gfx">{{ gfx.name }}</li>
</ul>
</td>
Assuming the selected application is set via a binding of {{ selectedApplication }} ($scope is implied), then your ng-repeat should look like:
<tr data-ng-repeat="driver in selectedApplication | filter: { name: selectedApplication } track by $index">
<td>{{ driver.gfx[$index].name }}</td>
</tr>
This means you'll be talking about the driver inside the selected application object.

.after() in angularjs (nested ng-repeat recursive iteration)

I have a simple structure
function linksRarrange($scope) {
$scope.links = [
{
text: 'Menu Item 1',
url: '#',
},{
text: 'Menu Item 2',
url: '#',
submenu: [
{
text: 'Sub-menu Item 3',
url: '#',
},{
text: 'Sub-menu Item 4',
url: '#',
submenu: [
{
text: 'Sub-sub-menu Item 5',
url: '#',
},{
text: 'Sub-sub-menu Item 6',
url: '#',
}
]
}
]
},{
text: 'Menu Item 3',
url: '#',
}
];
}
I wish to build a table where the children are rendered in a row the children after the parent eg:
Menu Item 1
Menu Item 2
Sub-menu Item 3
Sub-menu Item 4
Sub-menu Item 5
Sub-menu Item 6
Menu Item 3
<table>
<thead>
<tr>
<th>Title</th>
<th>Url</th>
</tr>
</thead>
<tbody>
<tr>
<td>Menu Item 1</td>
<td>#</td>
</tr>
<tr>
<td>Menu Item 2</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 3</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 4</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 5</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 6</td>
<td>#</td>
</tr>
<tr>
<td>Menu Item 3</td>
<td>#</td>
</tr>
</tbody>
</table>
I have looked at using ng-repeat-start and ng-repeat-end, but this doesn't support what I want to do.
Can anyone offer any help please?
If you are using this for navigation you can put it in a nested <ul> and us nice css to style it. something like:
<ul ng-repeat="menu in links">
<li>{{menu.text}}</li>
<ul ng-repeat="subs in menu.submenu">
<li>{{subs.text}}</li>
</ul>
<ul>
... something like that
Take a look at these resources:
https://groups.google.com/forum/#!msg/angular/TbpjE-5XEM0/yUi8wqc7sWoJ
http://sporto.github.io/blog/2013/06/24/nested-recursive-directives-in-angular/
I think the first example in the first link can be fitted to match your need.
This is definatly not the first time this question has been asked and I think you can find a lot more of these examples if not a direct hit at what you're looking for if you just google it up.
My current solution is not perfect, in fact the resulting html is not a table/tr but a set of nest ul/li elements that are then styled using css to emulate the design spec.
The causal factor is due to the problems with the placement of tbody an tr within a directive. If anyone has a workaround I would be very grateful for you to share this please.
The simple markup is as follows:
<menucollection menucollection='links'></menucollection>
Supported by 2 directives:
window.app.directive('menucollection', function () {
return {
restrict: "E",
replace: true,
scope: {
menucollection: '='
},
template: "<ul><menuitem ng-repeat='menuitem in menucollection' menuitem='menuitem'></menu></ul>"
}
});
window.app.directive('menuitem', function ($compile{
return {
restrict: "E",
replace: true,
scope: {
menuitem: '='
},
template: "<li>{{menuitem.Name}}</li>",
link: function (scope, element, attrs) {
scope.catMarker = attrs.marker;
scope.subcatMarker = attrs.marker + ' ยป ';
if (scope.menu.Children.length > 0) {
element.append('<menucollection menucollection="menu.submenu"></menucollection>');
$compile(element.contents())(scope);
}
}
};
});

Loop through array in array with Angular

Working on a TODO-app to learn Angular. I have this hardcoded array as a "database" and i want to display the tasks in the view.
var taskLists = [
{name: 'Todays todo', id: '1', tasks:['Make coffe', 'another task']},
{name: 'Tomorrow i will do this', id: '2', tasks:['Code well', 'go to bed']}
];
So how do i iterate through an array inside an array in an angular-view?
I tried to have two ng-repeats but cant get it to work right. I want to display the tasks one by one as <td>, not just the whole tasks array as one <td> as it does right now ['Make coffe', 'another task']
This is what the view looks like.
<h2 ng-repeat="object in list">{{object.name}}</h2>
<table>
<thead>
<tr>Tasks</tr>
</thead>
<tr>
<td ng-repeat="task in list">{{task.tasks}}</td>
</tr>
</table>
You have a problem in your logic.
Fist your HTML tag from child must be inside the parent.
<div class="parent" ng-repeat="object in list">
<h2>{{object.name}}</h2>
<table>
<thead>
<tr>Tasks</tr>
</thead>
<tr ng-repeat="task in object.tasks">
<td>{{item}}</td>
</tr>
</table>
</div>
Try this and check if it works.

Categories