ng-repeat over an array of objects (using ng-start) - angularjs

I have an array of objects that I am trying to display. The problem is that I can only access the data by calling it by it's property name. I would like to be to iterate through using the object's key.
The object has two properties and each property represents a start time and an end time. They're to be displayed in each cell.
My table is structured like this:
<table class="table table-striped">
<tr>
<th></th>
<th ng-repeat="department in departments" style="vertical-align:top" colspan="2">{{department}}</th>
</tr>
<tr ng-repeat="time in times">
<td>{{weekdays[$index]}}</td>
<td ng-repeat-start="dept in time">{{times[$index].service.start}}</td>
<td ng-repeat-end>{{times[$index].service.end}}</td>
</tr>
</table>
In this case, how can I dynamically access the object?
My controller:
.controller("businessHours", function($scope) {
$scope.weekdays = ["Sunday", "Monday", "Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
$scope.departments = ["sales", "service","accounting","bodyshop","other","parts"];
$scope.times = [];
$.each($scope.weekdays, function(index, value) {
var dayTimes = {};
$.each($scope.departments, function(index2, value){
console.log(index)
dayTimes[value] = {start: '5', end: '6'};
});
$scope.times.push(dayTimes);
});
})
Am I going about this correctly or is there a better way to arrange my data structure?

Iterate over the (key,value) in ng-repeat in angular:
Read more about ng-repeat:
<div ng-repeat="(key, value) in myObj"> ... </div>,
In your case, update your html where:
<td ng-repeat-start="(key,dept) in time">{{times[$index][key].start}}</td>
<td ng-repeat-end>{{times[$index][key].end}}</td>
angular.module('app', [])
.controller('homeCtrl', function($scope) {
$scope.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
$scope.departments = ["sales", "service", "accounting", "bodyshop", "other", "parts"];
$scope.times = [];
angular.forEach($scope.weekdays, function(v, i) {
var dayTimes = {};
angular.forEach($scope.departments, function(value, index) {
console.log(index)
dayTimes[value] = {
start: '5',
end: '6'
};
});
$scope.times.push(dayTimes);
});
console.info($scope.times);
});
td,tr {
text-align:center;
min-width: 20px;
}
<html>
<head>
<title>Single Demo</title>
<script src="//cdn.bootcss.com/jquery/2.2.1/jquery.js"></script>
<script src="//cdn.bootcss.com/angular.js/1.4.7/angular.js"></script>
</head>
<body ng-app="app" ng-controller="homeCtrl">
<div class="container">
<table class="table table-striped">
<tr>
<th></th>
<th ng-repeat="department in departments" style="vertical-align:top" colspan="2">{{department}}</th>
</tr>
<tr ng-repeat="time in times">
<td>{{weekdays[$index]}}</td>
<td ng-repeat-start="(key,dept) in time">{{times[$index][key].start}}</td>
<td ng-repeat-end>{{times[$index][key].end}}</td>
</tr>
</table>
</div>
</body>
</html>

Related

I want to calculate a total of ng-repeat

I want to calculate a total of amount of ng-repeat with the condition.
My table looks like this
<tr ng-repeat="Company in Companies track by $index">
<td>Departmend</td>
<td>Amount</td>
</tr>
<tr>
<td>HR</td>
<td>500</td>
</tr>
<tr>
<td>IT</td>
<td>200</td>
</tr>
<tr>
<td>HR</td>
<td>600</td>
</tr>
<tr>
<td colspan="2">Total:</td>
</tr>
My script like this.
<script>
if ($scope.Department == "HR") {
var Total = 0;
angular.forEach($scope.Companies, function (item) {
Total = Math.abs(Total) + Math.abs(item.Amount);
});
}
</script>
Are you looking for a solution like this? Finding the total of the array depending on its type?
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.Companies = [
{ Amount: 200, Department: "HR" },
{ Amount: 300, Department: "IT" },
{ Amount: 400, Department: "HR" },
{ Amount: 500, Department: "IT" },
{ Amount: 600, Department: "HR" }
];
$scope.totalValue = 0;
angular.forEach($scope.Companies, function(item) {
if (item.Department === "HR") {
$scope.totalValue += Math.abs(item.Amount);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body ng-app="myApp" ng-controller="myCtrl">
<table>
<tr>
<td>Departmend</td>
<td>Amount</td>
</tr>
<tr ng-repeat="Company in Companies track by $index">
<td>{{Company.Department}}</td>
<td>{{Company.Amount}}</td>
</tr>
<tr>
<td>Total</td>
<td>{{totalValue}}</td>
</tr>
</table>
</body>

AngularFire searching key node and assign to variable

I 'm working on my AngularFire project. I've a database something like this https://dinosaur-facts.firebaseio.com/. What I'm doing is first searching the key like the dinosaurs child such as "linhenykus" and storing its keys and values to other $scope variable.
my code in controller
var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs" + "/" + $scope.dinoID); //$scope.dinoID is variable containg dino keys
$scope.detRef = $firebaseArray(ref);
I'm getting the output like
[{"$value":-85000000,"$id":"appeared","$priority":null},{"$value":0.6,"$id":"height","$priority":null},{"$value":1,"$id":"length","$priority":null},{"$value":"theropoda","$id":"order","$priority":null},{"$value":-75000000,"$id":"vanished","$priority":null},{"$value":3,"$id":"weight","$priority":null}]
How to fetch the keys and values?
Use ngRepeat directive, as below:
<tr ng-repeat="obj in array track by $index">
To filter the array you can use the filter of Angular:
<tr ng-repeat="obj in array | filter: criteria track by $index">
Here's an example:
(function() {
angular
.module('app', [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', '$filter'];
function MainCtrl($scope, $filter) {
$scope.criteria = {};
$scope.array = [
{
"$value":-85000000,
"$id":"appeared",
"$priority":null
},
{
"$value":0.6,
"$id":"height",
"$priority":null
},
{
"$value":1,
"$id":"length",
"$priority":null
},
{
"$value":"theropoda",
"$id":"order",
"$priority":null
},
{
"$value":-75000000,
"$id":"vanished",
"$priority":null
},
{
"$value":3,
"$id":"weight",
"$priority":null
}
];
$scope.getObj = function(value, id) {
$scope.obj = $filter('filter')($scope.array, {
"$value": value,
"$id": id
})[0];
}
$scope.getObj("theropoda", "order");
}
})();
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<input type="text" placeholder="Search by value" ng-model="criteria.$value">
<input type="text" placeholder="Search by id" ng-model="criteria.$id">
<!-- Note that this button is just as an example to change the object displayed below -->
<button type="button" ng-click="getObj()">Change the value of object</button>
<hr>
Obj: <span ng-bind-template="Value: {{obj.$value}}, Id: {{obj.$id}}"></span>
<p></p>
<table width="100%">
<thead>
<tr>
<th>Value</th>
<th>Id</th>
<th>Priority</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="obj in array | filter: criteria track by $index">
<td ng-bind="obj.$value"></td>
<td ng-bind="obj.$id"></td>
<td ng-bind="obj.$priority"></td>
</tr>
</tbody>
</table>
</body>
</html>

angular angular-table dynamic header name

I use angular and angular-table to display multiple tables on the same page.
I need to create dynamic table with dynamic header and dynamic content.
Plunkr her
This is a working example with non dynamic header but I don't find how to make dynamic
The controller :
angular.module('plunker', ['ui.bootstrap',"angular-table","angular-tabs"]);
function ListCtrl($scope, $dialog) {
$scope.cols= ['index','name','email'];
$scope.list = [
{ index: 1, name: "Kristin Hill", email: "kristin#hill.com" },
{ index: 2, name: "Valerie Francis", email: "valerie#francis.com" },
...
];
$scope.config = {
itemsPerPage: 5,
fillLastPage: true
};
}
HTML
<!-- this work -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="name"></td>
<td at-implicit at-sortable at-attribute="email"></td>
</tr>
</tbody>
</table>
<!-- this fail ... -->
<table class="table table-striped" at-table at-paginated at-list="list" at-config="config">
<thead></thead>
<tbody>
<tr>
<td ng-repeat='col in cols' at-implicit at-sortable at-attribute="{{col}}"></td>
</tr>
</tbody>
</table>
I am missing some think or it is not possible with this module ?
Did you know another module where you can have dynamic header and pagination ? ( i try also ngTable but have some bug issu with data not being displayed )
Through the below code, you can generate dynamic header
<table class="table table-hover table-striped">
<tbody>
<tr class="accordion-toggle tblHeader">
<th ng-repeat="(key, val) in columns">{{key}}</th>
</tr>
<tr ng-repeat="row in rows">
<td ng-if="!$last" ng-repeat="col in key(row)" ng-init="val=row[col]">
{{val}}
</td>
</tr>
</tbody>
</table>
Angular Script
var app = angular.module('myApp', []);
app.controller('myControl', function ($scope, $http) {
$http.get('http://jsonplaceholder.typicode.com/todos').success(function (data) {
$scope.columns = data[0];
$scope.rows = data;
}).error(function (data, status) {
});
$scope.key = function (obj) {
if (!obj) return [];
return Object.keys(obj);
}
});

Create a table from scope object values

I have a table which I'm trying to create from a scope-object that I'm creating in my controller.
I would like the headers to take the value from 'rowHeader', which works fine. But the problem is that I wan't my cell values to be taken from 'cellValue' property.
In my fiddle I've added a "Desired table", thats how I would like the results to be in my first approach. If possible..
As you can see I would like to use a filter on one of the columns as well.
The reason that I would like to use this approach is so that I can use the checkboxlist to hide/show columns, and of course so that I can setup my table easy within the controller
Fiddle: http://jsfiddle.net/HB7LU/21469/
<!doctype html>
<html ng-app="plunker">
<head>
<script data-require="angular.js#*" data-semver="1.2.0" src="http://code.angularjs.org/1.2.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng:controller="MainCtrl">
<p>My table</p>
<table border="1">
<thead style="font-weight: bold;">
<tr>
<th class="text-right" ng-repeat="column in columnsTest" ng-if="column.checked" ng-bind="column.rowHeader"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows" border="1">
<td ng-repeat="column in columns" ng-if="column.checked" ng-bind="row[column.cellValue]"></td>
</tr>
</tbody>
</table>
<p>Visible Columns:</p>
<br />
<div class="cbxList" ng-repeat="column in columnsTest">
<input type="checkbox" ng-model="column.checked">{{column.rowHeader}}
</div>
</div>
<script>
var app = angular.module('plunker', []);
app.filter('percentage', function () {
return function (changeFraction) {
return (changeFraction * 100).toFixed(2) + "%";
}
});
app.controller('MainCtrl', function($scope) {
$scope.columnsTest = [
{ checked: true, cellValue: 'ModelName', rowHeader: 'Name' },
{ checked: true, cellValue: 'value1', rowHeader: 'PL' },
{ checked: true, cellValue: 'value1 / value2 | percentage', rowHeader: '+/-' }
];
$scope.rows = [
{ value1: 100, value2: 5, ModelName: "This is a cell value" },
{ value1: 15, value2: 5, ModelName: "This is a cell value2" },
{ value1: 38, value2: 2, ModelName: "This is a cell value3" }
];
});
</script>
</body>
</html>
There is a typo in the code cause the problem:
<tr ng-repeat="row in rows" border="1">
<td ng-repeat="column in columns"
ng-if="column.checked" ng-bind="row[column.cellValue]"></td>
</tr>
You don't have a scope variable called columns, change it to columnsTest.
<tr ng-repeat="row in rows" border="1">
<td ng-repeat="column in columnsTest"
ng-if="column.checked" ng-bind="row[column.cellValue]"></td>
</tr>

Can't generate <td> structure with recursive ng-repeat

I'm having some difficulties generating the desired table structure with a nest ng-repeat. I have a table header for each day of the week and I want to display three shifts in the <td> beneath that. Currently I solve this with three <span>'s in one <td>, but I would like to generate three <td>'s for each shift in on day. My html code with the repeats is:
<div>
<table>
<caption>Week: {{ week }}</caption>
<thead>
<tr>
<th ng-repeat="day in days">
<span>{{day.Date}}/{{ month }}/{{ year }}</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-repeat="day in days">
<span ng-repeat="shift in shifts">{{shift.Name}}</span>
</td>
</tr>
</tbody>
</table>
</div>
I have tried <th colspan="3"> with different placement of "day in days" repeats, but I can't seem to get the wanted structure for the table body:
<tr>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
<td>shift1</td>
<td>shift2</td>
<td>shift3</td>
</tr>
My question is: how can I rewrite my current code with the <span>'s so that it generates the wanted structure above.
If I understood your problem correctly then I think you are looking for ng-repeat-start & ng-repeat-stop.
HTML:
<div ng-app>
<div ng-controller="ExampleCtrl">
<table border="1">
<tr>
<td ng-repeat-start="day in days" ng-show="false"></td>
<td ng-repeat="shift in day.shifts" ng-repeat-end>shift{{shift}}</td>
</tr>
</table>
</div>
</div>
JS Controller:
function ExampleCtrl($scope) {
$scope.days = [
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
},
{
shifts: ["1","2","3"]
}
];
}
and the Fiddle
shifts outside days object: Fiddle update
You can create new plain list in your model to iterate over and use it instead of using nested loops. If data is to be changed then you can watch changes of dependent properties and reassemble plain list for each change. Something like this:
JavaScript
angular.module('app',[]).
controller('appController', function($scope) {
var i, j;
$scope.week = 1;
$scope.days = [{
day: 1,
month: 2,
year: 2014
}, {
day: 2,
month: 2,
year: 2014
}, {
day: 3,
month: 2,
year: 2014
}];
$scope.shifts = ['Shift1', 'Shift2', 'Shift3'];
// Create new plain list each time shifts is changed
$scope.$watchCollection('shifts', function() {
$scope.daysShifts = [];
for(i=0; i<$scope.days.length; i++) {
for(j=0; j<$scope.shifts.length; j++) {
$scope.daysShifts.push({
name: $scope.shifts[j]
});
}
}
});
$scope.addShift = function() {
$scope.shifts.push('Shift'+($scope.shifts.length+1));
}
});
HTML
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="angular.js#*" data-semver="1.2.11" src="http://code.angularjs.org/1.2.11/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="appController">
<div>
<table>
<caption>Week: {{week}}</caption>
<thead>
<tr>
<th ng-repeat="day in days" colspan="{{shifts.length}}">
<span>{{day.day}}/{{day.month}}/{{day.year}}</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td ng-repeat="dayShift in daysShifts">
<span>{{dayShift.name}}</span>
</td>
</tr>
</tbody>
</table>
</div>
<button ng-click="addShift()">Add Shift</button>
</body>
</html>
Plunker: http://plnkr.co/edit/zZYrurhp3HQA9Jp9QHDo?p=preview

Resources