AngularJs - ng-repeat not displaying data - angularjs

Can someone advise why the following is not working.
Controller:
(function () {
'use strict';
angular
.module("shop")
.controller("CartSummaryController", CartSummaryController);
function CartSummaryController($scope, cart) {
$scope.cartData = cart.getProducts();
console.log($scope.cartData);
$scope.total = function () {
var total = 0;
for (var i = 0; i < $scope.cartData.length; i++) {
total += ($scope.cartData[i].price * $scope.cartData[i].count);
}
return total;
}
$scope.remove = function (id) {
cart.removeProduct(id);
}
}
})();
Html:
Your Cart
<div ng-show="cartData.length == 0">
There are no products in your shopping cart.
</div>
<div ng-hide="cartData.length == 0">
<table class="table">
<thead>
<tr>
<th>Quantity</th>
<th>Item</th>
<th class="text-right">Price</th>
<th class="text-right">Subtotal</th>
</tr>
</thead>
</table>
<tbody>
<tr ng-repeat="item in cartData">
<td>{{item.count}}</td>
<td>{{item.name}}</td>
<td>{{item.price | currency}}</td>
<td>blah</td>
</tr>
</tbody>
</div>
Object printed to console:
Object
count
:
1
id
:
"1"
name
:
"item #1"
price
:
"100.00"
Furthermore, is there a way to debug the ng-repeat?

The label </table> should go after the label </tbody>

Related

How to use Nested ng-repeat to repeat table columns dynamically?

I want to make dynamic columns of a table and create a new object to save it in mongoDb.
I have first Array of Student as:
students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
and have second Array of Subjects as:
subjects = [{sName: "maths"},{sName: "science"}]
Here is the HTML
<div ng-app='t' ng-controller='test'>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th ng-repeat="subject in subjects">{{subject.sName}}</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in finalData track by $index">
<th><input type="text" ng-model="row.rollNo"/></th>
<th><input type="text" ng-model="row.fullName"></th>
<th ng-repeat="subject in subjects"><input type="text" ng-model="row.marks"></th>
<th>
<button ng-click="action($index)">
add/remove
</button></th>
</tr>
</tbody>
</table>
</div>
Here is the Controller
(function(){
var app = angular.module('t', []);
app.controller('test',
[
'$scope',
function($scope)
{
$scope.students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
$scope.subjects = [{sName: "maths"},{sName: "science"}]
$scope.finalData = new Array();
$scope.finalData.push({
icon : false
});
$scope.action=function(index){
if(index == $scope.finalData.length-1){
$scope.finalData[index].icon = true;
$scope.finalData.push({
icon : false
});
}else{
$scope.finalData.splice(index, 1);
}
};
}
]);
})();
The Output Looks like this.
The marks columns are repeating similar values. But i want one single finalObject to save my data.
Here is the jsFiddle of my problem https://jsfiddle.net/g8tn71tr/
The row subjects refer to the same NgModel row.marks which makes them have the same value.
You can solve it by making the ng-model refer to each of the subjects ng-model="row.marks[subject.sName]". This will result in that row.marks will become an object where each subject will be a key and the model will be in its value
(function(){
var app = angular.module('t', []);
app.controller('test',
[
'$scope',
function($scope)
{
$scope.students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
$scope.subjects = [{sName: "maths"},{sName: "science"}]
$scope.finalData = new Array();
$scope.finalData.push({
icon : false
});
$scope.action=function(index){
console.clear();
console.log($scope.finalData[index]);
if(index == $scope.finalData.length-1){
$scope.finalData[index].icon = true;
$scope.finalData.push({
icon : false
});
}else{
$scope.finalData.splice(index, 1);
}
};
}
]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app='t' ng-controller='test'>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th ng-repeat="subject in subjects">{{subject.sName}}</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in finalData track by $index">
<th><input type="text" ng-model="row.rollNo"/></th>
<th><input type="text" ng-model="row.fullName"></th>
<th ng-repeat="subject in subjects"><input type="text" ng-model="row.marks[subject.sName]"></th>
<th>
<button ng-click="action($index)">
add/remove
</button></th>
</tr>
</tbody>
</table>
</div>

How to Sum From Multi object

Please help me, I'm using 2 JSON feed, need to display array value in one table then add sum row for each column, but I don't know how to call Expense Table and sum it.
Income JSON Table:
nominal_income
Expense JSON Table:
nominal_expense
If you have any example please let me know :D
My HTML:
<table ng-controller="incomeCtrl">
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes" ng-init="$last ? runEvent(item) : null">
<td class="text-left">{{item.nominal_income}}</td>
<td class="text-left">{{item.nominal_expense}}</td> // how to call this?
</tr>
<tr>
<td class="text-left" >{{ income_total | number:2 }}</td>
<td class="text-left" >{{ expense_total | number:2 }}</td> //how to sum this ?
</tr>
</table>
JS Controller:
$scope.runEvent = function(item) {
var income_total = 0;
angular.forEach(item, function(item) {
income_total = income_total -(- incomes.nominal_income)
;})
$scope.income_total = income_total;}
Use a custom function and call the function with key parameter
angular.module("test",[]).controller("testc",function($scope) {
$scope.incomes=[{nominal_income:20,nominal_expense:75.5},{nominal_income:30.00,nominal_expense:14.50},{nominal_income:49.99,nominal_expense:10}]
$scope.average = function(array, key) {
var value= 0,
average;
for (var i = 0; i < array.length; i++) {
value+= array[i][key];
}
return value;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="testc">
<table >
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes" ng-init="$last ? runEvent(item) : null">
<td class="text-left">{{item.nominal_income}}</td>
<td class="text-left">{{item.nominal_expense}}</td>
</tr>
<tr>
<td style="color:green" class="text-left" >{{average(incomes,"nominal_income") | number:2 }}
</td>
<td style="color:green" class="text-left" >{{average(incomes,"nominal_expense") | number:2 }}
</td>
</tr>
</table>
</div>
Update: How to join IncomeCtrl and ExpenseCtrl
You can call another controller inside a controller as nested controller. Or you can pass the data from one controller to another controller by using $routScope or $Cookies or $service or $BroadCase etc
<table ng-controller="incomeCtrl">
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes" ng-init="$last ? runEvent(item) : null">
<td class="text-left">{{item.nominal_income}}</td>
<td ng-controller="ExpenseCtrl" class="text-left">{{expenses[$index].nominal_expense}}</td> // may you need $$parent.$index
</tr>
<tr>
<td style="color:green" class="text-left" >{{average(incomes,"nominal_income") | number:2 }}
</td>
<td ng-controller="ExpenseCtrl" style="color:green" class="text-left" >{{average(expenses,"nominal_expense") | number:2 }}
</td>
</tr>
</table>
You can pass a type / column as a parameter to be reduced to get the sum. Here is an example:
var app = angular.module('myApp', []);
app.controller('incomeCtrl', function($scope, incomeService) { // incomeService injected here as a serivce
var inc = incomeService.get_income();
var exp = incomeService.get_expense();
$scope.incomes = [];
/* works if `inc` and `exp` have the same length, merge with caution! */
for (var i = 0; i < inc.length; i++) {
$scope.incomes.push({
"nominal_income": inc[i],
"nominal_expense": exp[i]
})
}
$scope.sum = function(type) {
return $scope.incomes.reduce((x, y) => {
return x + y[type];
}, 0);
}
});
app.factory('incomeService', function() {
var service = {};
var data = {
"income": [2.01, 3.23, 6.56],
"expense": [1.12, 2.34, 5.67]
}
service.get_income = function() {
return data.income;
}
service.get_expense = function() {
return data.expense;
}
service.set_income = function(array) { // populated in incomeCtrl
data.income = array;
}
service.set_expense = function(array) { // populated in expenseCtrl
data.expense = array;
}
return service;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="incomeCtrl">
<table>
<tr>
<td>Income</td>
<td>Expense</td>
</tr>
<tr ng-repeat="item in incomes">
<td class="text-left">{{item.nominal_income}}</td>
<td class="text-left">{{item.nominal_expense}}</td>
</tr>
<tr style="color:red;">
<td class="text-left">{{sum('nominal_income') | number:2}}</td>
<td class="text-left">{{sum('nominal_expense') | number:2}}</td>
</tr>
</table>
</div>

AngularJS - Summing filtered rows in table

Based in this example I need to sum the ages of the filtered users. It means, if I have three names filtered, the filter in the controller must to sum only these the ages.
html
<div data-ng-app="app" data-ng-controller="controller">
<input type="text" data-ng-model="parameter" placeholder="search">
<p/>
<table border="1">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Age</th>
</tr>
<thead>
<tbody>
<tr data-ng-repeat="user in users | filter: parameter">
<td>{{$index+1}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Total ages</td>
<td>{{users | sumByKey: 'age'}}</td>
</tr>
</tfoot>
</table>
</div>
angularjs
var app = angular.module("app", []);
app.filter('sumByKey', function() {
return function(data, key) {
if (typeof(data) === 'undefined' || typeof(key) === 'undefined') {
return 0;
}
var sum = 0;
for (var i = data.length - 1; i >= 0; i--) {
sum += parseInt(data[i][key]);
}
return sum;
};
});
Any idea?
You could store the filtered data in a filteredList and pass it for the calculation,
<tbody>
<tr data-ng-repeat="user in (filteredList = (users | filter: parameter))">
<td>{{$index+1}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Total ages</td>
<td>{{filteredList | sumByKey: 'age' }}</td>
</tr>
</tfoot>
DEMO

ng-repeat add data to table rows

My aim is to get the table to display data like the one below. I manage to display the years on top and first vertical column(company) down but how do I get yield data for each company and display it in each row? ps. I am very new to angular.
<table>
<thead>
<tr><th></th><th>2015</th><th>2016</th><th>2017</th><th>2018</th><th>2019</th></tr>
</thead>
<tbody>
<tr><td>ABC</td><td>2.03</td><td>2.22</td><td>2.44</td><td>2.57</td><td>2.69</td></tr>
<tr><td>DEF</td><td>1.08</td><td>1.14</td><td>1.19</td><td>1.25</td><td>1.32</td></tr>
</tbody>
</table>
JSON
{
"years":[
2015,
2016,
2017,
2018,
2019
],
"yields":[
{
"company":"ABC",
"yield":{
"2015":2.03000,
"2016":2.22000,
"2017":2.44000,
"2018":2.57000,
"2019":2.69000
}
},
{
"company":"DEF",
"yield":{
"2015":1.08000,
"2016":1.14000,
"2017":1.19000,
"2018":1.25000,
"2019":1.32000
}
}
]
}
HTML
<table data-ng-controller="dividendController as divd">
<thead>
<tr>
<th></th>
<th data-ng-repeat="y in year">{{y}}</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="c in yields">
<td>{{c.company}}</td>
<td data-ng-repeat="n in divYield">{{n}}</td>
</tr>
</tbody>
</table>
CONTROLLER
(function (angular) {
'use strict';
angular.module('example', [])
.controller('dividendController', function ($scope, $http) {
$http.get("api/myapi/myexample")
.success(function (response) {
$scope.year = response.years;
$scope.yields = response.yields;
$scope.divYieldList = [];
$scope.company = [];
angular.forEach(response.yields, function (obj, index) {
$scope.company.push(obj.company);
$scope.divYield = [];
angular.forEach(obj.yield, function (yld, index) {
$scope.divYield.push(yld);
});
$scope.divYieldList.push($scope.divYield);
});
});
});
})(window.angular);
<div ng-init='TesData={"years":[2015,2016,2017,2018,2019],"yields": [{"company":"abc","yield":{"2015":2.03000,"2016":2.22000,"2017":2.44000,"2018":2.57000,"2019":2.69000} },{"company":"def","yield":{"2015":1.08000,"2016":1.14000,"2017":1.19000,"2018":1.25000,"2019":1.32000}}]};'>
<table>
<thead>
<tr>
<th></th>
<th data-ng-repeat="y in TesData.years">{{y}}</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="c in TesData.yields">
<td>{{c.company}}</td>
<td data-ng-repeat="n in c.yield">{{n}}</td>
</tr>
</tbody>
</table>
</div>

How do I update this Angular cart from a separate product controller?

I have the cart working but I can't seem to figure out how to add items to the cart correctly from a separate product controller. I've been playing with services and factories but I cant get my head around how to make them work.
http://jsfiddle.net/75m7e/823/
HTML
<h2>Shopping Card Example</h2>
<div ng:controller="CartForm">
<table class="table">
<tr>
<th>Description</th>
<th>Qty</th>
<th>Cost</th>
<th>Total</th>
<th></th>
</tr>
<tr ng:repeat="item in invoice.items">
<td><input type="text" ng:model="item.description"class="input-small"></td>
<td><input type="number" ng:model="item.qty" ng:required class="input-mini"></td>
<td><input type="number" ng:model="item.cost" ng:required class="input-mini"></td>
<td>{{item.qty * item.cost | currency}}</td>
<td>
[<a href ng:click="removeItem($index)">X</a>]
</td>
</tr>
<tr>
<td><a href ng:click="addItem()" class="btn btn-small">add item</a></td>
<td></td>
<td>Total:</td>
<td>{{total() | currency}}</td>
</tr>
</table>
</div>
JavaScript
function CartForm($scope) {
$scope.invoice = {
items: [{
qty: 10,
description: 'item',
cost: 9.95}]
};
$scope.addItem = function() {
$scope.invoice.items.push({
qty: 1,
description: '',
cost: 0
});
},
$scope.removeItem = function(index) {
$scope.invoice.items.splice(index, 1);
},
$scope.total = function() {
var total = 0;
angular.forEach($scope.invoice.items, function(item) {
total += item.qty * item.cost;
})
return total;
}
}
I want to click the add to cart button within the product controller and expose the products data to the cart controller, adding the item to the list. What's the best way to do this?

Resources