Add a few table cells with AngularJS - angularjs

I am using Angular.js and ng-repeat directive for creating a table cells. I have array with object:
$scope.items = [{ name: 'item1', value: [{ val1: '1' }, { val2: '2' }] },
{ name: 'item2', value: [{ val1: '3' }, { val2: '4' }] ]
and here is my markup:
<tr ng-repeat="item in items" >
<td>{{item.name}}</td>
<td ng-repeat="another_item in item.value">{{another_item.val1 + another_item.val2}}</td>
</tr>
Can somebody explain me, why is the second construction with td generate two tags. How does this construction work with plus in this case: {{another_item.val1 + another_item.val2}}
Thank you.

ngRepeat iterates through the array and add the element it is in to the dom for every value.
In your case, iterating through items will add the following:
<tr ng-repeat="item1" >
<td>{{item1.name}}</td>
<td ng-repeat="another_item in item2.value">{{another_item.val1 + another_item.val2}}</td>
</tr>
<tr ng-repeat="item2" >
<td>{{item2.name}}</td>
<td ng-repeat="another_item in item2.value">{{another_item.val1 + another_item.val2}}</td>
</tr>
The inner ng-repeat does the same, so it becomes:
<tr ng-repeat="item1" >
<td>{{item1.name}}</td>
<td ng-repeat="firstIndex">{{firstIndex.val1 + firstIndex.val2}}</td>
<td ng-repeat="secondIndex">{{secondIndex.val1 + secondIndex.val2}}</td>
</tr>
<tr ng-repeat="item2" >
<td>{{item2.name}}</td>
<td ng-repeat="firstIndex">{{firstIndex.val1 + firstIndex.val2}}</td>
<td ng-repeat="secondIndex">{{secondIndex.val1 + secondIndex.val2}}</td>
</tr>
See why it does not work? Since firstIndex only has val1, fails to add with val2. Opposite for secondIndex.

Related

AngularJS recursive templates using tables

I am trying to work out how to do recursion using table tags with angularjs. I have the following data structure
$scope.report = [{
'Name': 'Moo',
'Value': 'MooV',
'Children': [{
'Name': 'Moo2',
'Value': 'Moo2V',
'Children': [{
'Name': 'Moo3',
'Value': 'Moo3V'
}]
}]
}];
The recursion can have no limit. I am looking to put in a simple table with the format
<table>
<tr>
<td>Moo</td>
<td>MooV</td>
</tr>
<tr>
<td>Moo2</td>
<td>Moo2V</td>
</tr>
<tr>
<td>Moo3</td>
<td>Moo3v</td>
</tr>
<table>
but I am unable to get it working just right. This will allow me to do certain things to the sections while looking flat to the user. Currently I have the code
<div ng-app="app" ng-controller='AppCtrl'>
<script type="text/ng-template" id="rloop">
<td>{{data.Name}}</td>
<td>{{data.Value}}</td>
<tr ng-repeat="data in data.Children" ng-include src="'rloop'"></tr>
</script>
<table class="table table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="data in report" ng-include="'rloop'"></tr>
<tr ng-repeat-end></tr>
</tbody>
</table>
</div>
but this is not going to work due to in repeating it creates a tr tag within a tr tag. I have tried various different methods of moving the repeat to tbody etc etc but I can't seems to get it working due to the restrictions of tables in HTML. Example, is not allowed within tr.
JSFiddle showing issue here: JSfiddle
As you say, this is not going to work within the table. Maybe it would be better to recursively convert the data to an array of Name/Value pairs, then use those in the normal way?
var app = angular.module('app', []);
function includeChildren([first, ...rest]) {
if (!first) return [];
const {Name, Value, Children = []} = first;
return [{Name, Value}, ...includeChildren(Children), ...includeChildren(rest)];
}
app.controller('AppCtrl', function ($scope) {
$scope.report = [{
'Name': 'Moo',
'Value': 'MooV',
'Children': [{
'Name': 'Moo2',
'Value': 'Moo2V',
'Children': [{
'Name': 'Moo3',
'Value': 'Moo3V'
}]
}]
}];
$scope.reportTable = includeChildren($scope.report);
// $scope.reportTable now contains:
// [{Name: 'Moo', Value: 'MooV'}, {Name: 'Moo2', Value: 'Moo2V'}, {Name: 'Moo3', Value: 'Moo3V'}]
});
Now you can use a more unsurprising template:
<div ng-app="app" ng-controller='AppCtrl'>
<table class="table table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="data in reportTable">
<td>{{data.Name}}</td>
<td>{{data.Value}}</td>
</tr>
</tbody>
</table>
</div>
See it working here: https://jsfiddle.net/k6rf9g1p/1/

Trying to populate html table with ng-repeat using two different arrays

I am having some issues trying to populate a table with two arrays. I am trying to achieve the following output:
I have an array called students and within each student object, I have a courses array. I am trying to populate my table using ng-repeat to show all courses against each student.
Not all data is given within each course, meaning that if a student hasn't started a course then it won't appear in the courses array. Also, if a student hasn't finished a course there will be no date completed given.
So my array looks like so:
$scope.students = [
{
Id: 1,
Name: 'Joe Blogs',
Courses: [
{
Title: 'Course 1',
Grade: 87,
Completed: true,
DateCompleted: '2018-01-01'
},
{
Title: 'Course 2',
Grade: 2,
Completed: false
}
]
},
{
Id: 2,
Name: 'Peter Smith',
Courses: [
{
Title: 'Course 1',
Grade: 100,
Completed: true,
DateCompleted: '2018-01-01'
},
{
Title: 'Course 2',
Grade: 95,
Completed: true,
DateCompleted: '2018-01-01'
},
{
Title: 'Course 3',
Grade: 10,
Completed: false
}
]
},
{
Id: 3,
Name: 'Joanne Someone',
Courses: [
{
Title: 'Course 3',
Grade: 55,
Completed: false,
}
]
}
]
So far my code snippet looks like this:
<table class="table table-hover" width="100%">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Course</th>
<th>Grade</th>
<th>Completed</th>
<th>Date Completed</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="student in students">
<td>{{ student.Id }}</td>
<td>{{ student.Name }}</td>
<td>
<!-- Can't figure this bit out -->
</td>
</tr>
</tbody>
</table>
But I am stuck on how to get multiple courses to show against each student. Also I have found that by using ng-repeat, if a value isn't in the object (e.g. Date Completed) then that field will not show and pushes everything up and out of alignment.
Lastly, I will mention that I am using angular-datatables however, I am just trying to work out the concept, then I can apply this to datatables later.
You'll have to use rowspan for that purpose. And the value of that for particular Id should be of length of Courses. Then, you'll need to have ng-repeat on tbody to repeat tbody section & have ng-repeat inside on tr for repeating Courses arrays of each student. So, your table view code can be:
<table>
<thead>
<tr>
<td>Id</td>
<td>Name</td>
<td>Course</td>
<td>Grade</td>
<td>Completed</td>
<td>Date Completed</td>
</tr>
</thead>
<tbody ng-repeat="x in students">
<tr>
<td rowspan="{{x.Courses.length}}"><span>{{ x.Id }}</span></td>
<td rowspan="{{x.Courses.length}}"><span>{{ x.Name }}</span></td>
<td><span>{{x.Courses[0].Title}}</span></td>
<td><span>{{x.Courses[0].Grade}}</span></td>
<td><span>{{x.Courses[0].Completed}}</span></td>
<td><span>{{x.Courses[0].DateCompleted}}</span></td>
</tr>
<tr ng-repeat="item in x.Courses" ng-if="$index > 0">
<td><span>{{item.Title}}</span></td>
<td><span>{{item.Grade}}</span></td>
<td><span>{{item.Completed}}</span></td>
<td><span>{{item.DateCompleted}}</span></td>
</tr>
</tbody>
</table>
To avoid breaking of table code if some values are not available, just have it inside span element so it'll still load td with no value inside it.
Plunker Example

How to sort a nested table that has multiple ng-repeats angularjs

I have searched for a similar example and found lost of examples but none of them have the same datastructure as my json data so I have tried it all without success. This is my json data
vm.result = [
{
'first': [
{"indicate":"all", "text":"All views"},
{"indicate":"userview", "text":"User view"},
{"indicate":"operatorview", "text":"Operator view"}
]
},
{
'second': [
{"indicate":"receipts","text":"Receipts"},
{"indicate":"other", "text":"Other"},
{"indicate":"error", "text":"Error resolver"}
]
}
];
This is my table
<table class="table" >
<thead>
<tr>
<th ng-show="column">Key</th>
<th>Master</th>
<th>Editable</th>
</tr>
</thead>
<tbody ng-repeat="res in vm.result track by $index">
<tr ng-repeat="ed in res.first | filter: searchfield | orderBy: 'indicate' track by $index">
<td {{ed.indicate}}</td>
<td>{{ed.text}}</td>
<td> {{vm.result[1].second[$index].indicate}}</td>
<td > {{vm.result[1].second[$index].text}}</td>
</tr>
</tbody>
</table>
OrderBy only works for the first array but not the second and yes I have tried removing first after re in the second ng-repeat but then it cannot recognize it as an array. I need this structure in the table so that each array has its own columns for its data. So how to I add orderBy indicate for both arrays?
Expected output:
Master Editable
all | All | receipts | Receipts
userview | User view | other |Other
The format of result data is very poor. It is very hard to convert your expected output.
Try to use result array like this or convert to this type of format,
$scope.newResult = [{
first:{"indicate":"all", "text":"All views"},
second:{"indicate":"receipts","text":"Receipts"}
},
{
first:{"indicate":"userview", "text":"User views"},
second:{"indicate":"other","text":"Other"}
},
{
first:{"indicate":"operatorview", "text":"Operator views"},
second:{"indicate":"error","text":"Error resolver"}
}
]
HTML Code
<table >
<thead>
<tr>
<th>Key</th>
<th colspan="2">Master</th>
<th colspan="2">Editable</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="res in new">
<td>{{$index+1}}</td>
<td>{{res.first.indicate}}</td>
<td>{{res.first.text}}</td>
<td>{{res.second.indicate}}</td>
<td>{{res.second.text}}</td>
</tr>
</tbody>
</table>
Controller
$scope.result = [
{
'first': [
{"indicate":"all", "text":"All views"},
{"indicate":"userview", "text":"User view"},
{"indicate":"operatorview", "text":"Operator view"}
]
},
{
'second': [
{"indicate":"receipts","text":"Receipts"},
{"indicate":"other", "text":"Other"},
{"indicate":"error", "text":"Error resolver"}
]
}
];
$scope.new=[];
angular.forEach($scope.result, function(value, key) {
if(key ===0){
angular.forEach(value.first, function(val, k) {
$scope.new.push({'first':val,'second':''});
})
}
if(key ===1){
angular.forEach(value.second, function(val, k) {
$scope.new[k].second = val;
})
}
});
Using this type of mechanism you can get the expected output, but the better way is using good data format for result array.
jsfiddle for this.

How can I use AngularJS 1 to create table rows with the attributes of an array of objects?

So far I've only found examples that put the objects in the rows (1)(2)(3), but I need to put the objects in the columns and their attributes in the rows.
Example of JSON:
[
{
name: 'peanut butter',
price: 0.99
}
{
name: 'strawberry jelly',
price: 0.99
}
{
name: 'white bread',
price: 2.99
}
]
Example of desired table:
I think you want something like this.
Angular template:
<table>
<tr>
<th>Name</th>
<th ng-repeat="item in yourList">{{ item.name }}</th>
</tr>
<tr>
<td>Price</td>
<td ng-repeat="item in yourList">{{ item.price }}</td>
</tr>
</table>

Is there a way I can duplicate the "look up" functionality of an HTML <select> with AngularJS

I have an application that presents a table of data on a screen.
The table has an Id column, a Description column and a Created By column
Data comes from two javascript arrays:
var rowData = [{ id: 1, desc: 'A', createdBy: 1 },
{ id: 2, desc: 'B', createdBy: 6 }];
var users = [{ id: 1, name: 'jeff' },
{ id: 2, name: 'jane' },
[ id: 6, name: 'jake' }];
Here is the HTML I am using. Note that to display the Created By as a name I use a <select> that is source from the users array
<table>
<tr data-ng-repeat="row in rowData">
<td>{{ row.id }}</td>
<td>
<select
data-ng-disabled="true"
data-ng-model="row.createdBy"
data-ng-options="item.id as item.name for item in users">
</select></td>
</tr>
</table>
Using a <select> seems to work but seems like a very messy way to implement the look up and I see a select drop down which is disabled where I would really just like to see the name as text.
Without making any changes to the source arrays is there a way that I could put this look up into code or some kind of a directive. Note that the CreatedBy data is read only.
You could just loop through the users list and find the name by createdBy:
JSFiddle: http://jsfiddle.net/CdqTN/
Create a function that accepts createdBy. Then match it in a for loop:
$scope.getUser = function (createdBy) {
for (var i = 0; i < $scope.users.length; i++)
if ($scope.users[i].id === createdBy)
return $scope.users[i].name;
return '';
}
Then call it in your HTML:
<table>
<tr data-ng-repeat="row in rowData">
<td>{{ row.id }}</td>
<td>
{{ getUser(row.createdBy) }}
</td>
</tr>
</table>

Resources