foreach to foreach array in angularjs - angularjs

I am trying to update specific data of an array that is being displayed thru ng-repeat.
Given the datas:
$scope.cartItems = [];
$scope.items = [{code: 'ABC', cash:'20.00', charge: '25.00'},
{code: 'DEF', cash:'10.00', charge: '15.00'},{code:
'GHI',cash:'30.00', charge: '35.00'}];
then i have this table
Item | Price | Action
ABC | 20.00 | Add
DEF | 10.00 | Add
ng-click="add(Item,Price)"
$scope.add = function(Item,Price){
var itemscart = {};
itemscart.code = Item;
itemscart.price = Price;
$scope.cartItems.push(itemscart)
}
and is being displayed like this thru html table.
ng-repeat="cart in cartItems"
Item | price | bracket
ABC | 20.00 | Cash //dropdown
DEF | 10.00 | Cash //dropdown
And i have this dropdown select tag with option value; "Cash" or "Charge"
If in the dropdown i selected charge. The expected output of the html table must be:
Item | price | braket
ABC | 25.00 | Charge //dropdown
DEF | 15.00 | Charge //dropdown
I have tried:
if($scope.optionval == 'Charge'){
var price = 0;
$scope.cartItems.forEach(function(v){
if(v.code == ($scope.items.forEach(function(c){c.code; price =
c.charge; })))
v.PRICE = price;
console.log(v.PRICE) //gets the last row
console.log(price) //null
});
}

As per your displayed and expected table, you can try something like:
On change of CASH to CHARGE, make a function call on ng-change in
which pass the selected object with selected 'braket'.
Then in function call you can filter data.

In my opinion you could use a different approach, like using ng-show or ng-if directives to get the results you are trying to achieve
Try adding a custom field in your $scope in order to store which price should be shown, then you have two choices: to modify every field or separately:
Display independiently:
app.js
$scope.items = [{code: 'ABC', cash:'20.00', charge: '25.00', displaying:'cash'},{...}
HTML
<tr>
<th>Item</th>
<th>Price</th>
<th></th>
</tr>
<tr ng-repeat="cart in whatever">
<td>{{cart.item}}</td>
<td ng-show="cart.displaying=='cash'>{{cart.cash}}</td>
<td ng-show="cart.displaying=='charge'>{{cart.charge}}</td>
<td>{{cart.displaying}}</td>
<td>*Dropdown to modify this specific 'displaying' field*</td>
</tr>
Every field at the same time:
app.js
$scope.displayingitems = 'cash'
HTML
*Dropdown to modify this specific 'displaying' field*
<tr>
<th>Item</th>
<th>Price</th>
<th></th>
</tr>
<tr ng-repeat="cart in whatever">
<td>{{cart.item}}</td>
<td ng-show="displayingitems=='cash'>{{cart.cash}}</td>
<td ng-show="displayingitems =='charge'>{{cart.charge}}</td>
<td>{{displayingitems}}</td>
<td></td>
</tr>

Related

Filter on column and also sort in descending order in AngularJS

How can I sort in descending order but also filter on column in AngularJS? I have the following code that will default to the most recent timestamp.
<tr ng-repeat="item in log | orderBy:'-timestamp' ">
<td>{{item.timestamp | date: 'MM/dd/yyyy HH:MM'}}</td>
<td>{{item.Action | removeHTMLTags | strip }}</td>
<td>{{item.AO}}</td>
</tr>
I also have the following js code that will work for filtering on the column header.
$scope.reverseOrder = true;
$scope.sortField = '';
$scope.sortBy = function(sortField) {
$scope.reverseOrder = ($scope.sortField == sortField) ? !$scope.reverseOrder : false;
$scope.sortField = sortField;
}
<tr ng-repeat="item in log | orderBy:sortField:reverseOrder">
<td>{{item.timestamp | date: 'MM/dd/yyyy HH:MM'}}</td>
<td>{{item.Action | removeHTMLTags | strip }}</td>
<td>{{item.AO}}</td>
</tr>
I would like to both filter on the column but also default to show the most recent timestamps on top.
I tried the following but it did not work.
ng-repeat="item in log | orderBy:sortField:reverseOrder | orderBy: '-timestamp'"
In order to understand why your code isn't working you must understand first, how the orderBy filter works in angularjs. In your ng-repeat the orderBy filter has two parameters sortField and reverseOrder. For them to work you must have a controller that has two $scope variables named respectively sortField and reverseOrder. The first parameter is to determine which key should orderBy use to order your array and the second one is a boolean that specifies would the order be reversed or not.
In my attempt to reproduce your example, I took the liberty of using unix timestamps in my logs array. So in the controller,
$scope.searchText = "";
$scope.sortField = "timestamp";
$scope.reverseOrder = false;
$scope.logs = [
{
timestamp : 2147450400000,
Action : 'bal sal',
AO : 'abcd'
},
{
timestamp : 979840800000,
Action : 'bal sal2',
AO : 'abcd2'
},
{
timestamp : 1579370400000,
Action : 'bal sal2',
AO : 'abcd2'
}
]
$scope.sortBy = function(sortField) {
$scope.reverseOrder = ($scope.sortField === sortField) ? !$scope.reverseOrder : false;
$scope.sortField = sortField;
};
Also in the example you provided, they passed the column name via a function. So in your html you need to have something like this.
<input type="text" ng-model="searchText">
<table>
<thead>
<th ng-click="sortBy('timestamp')">Time Stamp</th>
<th ng-click="sortBy('Action')">Action</th>
<th ng-click="sortBy('AO')">AO</th>
</thead>
<tr ng-repeat="item in logs | orderBy:sortField:reverseOrder| filter:searchText">
<td>{{item.timestamp | date :'MM/dd/yyyy HH:MM'}}</td>
<td>{{item.Action}}</td>
<td>{{item.AO}}</td>
</tr>
</table>
Hope this clears your confusions.

Displaying data with ng-repeat from JSON array in angular

Hi I have following data that is returned from service which I do not have any control on how it is returned:
{"day_1":[{"classroom":"Nursery","count":0},{"classroom":"Junior Kindy","count":1}],"day_2":[{"classroom":"Nursery","count":4},{"classroom":"Junior Kindy","count":0}]}
but I need to display it in pivot format that is like below:
classroom | day_1 | day_2
============ ======== ======
Nursery | 0 | 4
Junior Kindy | 1 | 0
This is the code in controller
$scope.rolls=[];
Rolls.getRollMarked().then(
function(data){
console.log(data.data);
$scope.rolls = data.data;
}
)
in the view I am using following but it doesn't display any count for the day and I am not sure how to display it..so please let me know how can I display it in the above format?
<table class="table table-bordered">
<tr>
<td>Classroom</td>
<td>day_1</td>
<td>day_2</td>
</tr>
<tr ng-repeat="roll in rolls">
<td>
{{roll[$index]['classroom']}}
</td>
<td>
{{roll.day_1}}
</td>
<td>
{{roll.day_2}}
</td>
</tr>
</table>
You need to convert your data. ng-repeat as you have set it up expects an array.
Using some easy code you can get it to an array though, and then your code will work alright.
Also, you should update your html. You don't need to reference items using $index since each item is bound to the iterator variable in that case
<table class="table table-bordered">
<tr>
<th>Classroom</th>
<th>day_1</th>
<th>day_2</th>
</tr>
<tr ng-repeat="roll in rolls">
<td>
{{roll.classroom}}
</td>
<td>
{{roll.day_1}}
</td>
<td>
{{roll.day_2}}
</td>
</tr>
</table>
And then call a convert function that makes the data into an array. I've used lodash.find here, so you either need to reference that or use your own find method.
Rolls.getRollMarked().then(
function(data){
console.log(data.data);
$scope.rolls = convert(data.data);
}
)
function convert(json) {
var rolls = [];
var days = ['day_1', 'day_2'];
for (var d = 0; d < days.length; ++d) {
var day = days[d];
for (var i = 0; i < json[day].length; ++i) {
var classroom = json[day][i];
var existing = _.find(rolls, { "classroom": classroom.classroom });
if (!existing) {
existing = { classroom: classroom.classroom };
rolls.push(existing);
}
existing[day] = classroom.count;
}
}
return rolls;
}

How to sum in each row the values of before rows in specific column?

I've simulated my problem in this fiddle.
I have this HTML:
<table ng-app='Payments'>
<thead>
<tr>
<th>Date</th> <th>Cash</th> <th>Total</th>
</tr>
</thead>
<tbody ng-controller='paymentsController'>
<tr ng-repeat='pay in payments | orderBy : "date"'>
<td>{{pay.date}}</td>
<td><input type="textbox" ng-model="pay.cash"/></td>
<td></td>
</tr>
</tbody>
</table
And this JS:
var appModule = angular.module('Payments', []);
appModule.controller('paymentsController', function($scope) {
$scope.payments = [
{'id' : '1', 'date' : '2015-07-27', 'cash' : '149.98'},
{'id' : '2', 'date' : '2015-07-29', 'cash' : '70.00'},
{'id' : '3', 'date' : '2015-07-27', 'cash' : '129.99'},
{'id' : '4', 'date' : '2015-07-28', 'cash' : '349.90'}
];
});
How do I fill the third column with Angular?
The third column should be initially:
149.98 // due to 0.00 + 149.98
279.97 // due to 149.98 + 129.99
629.87 // due to 279.97 + 349.90
699.87 // due to 629.87 + 70.00
Then, ng-model should do the trick to update them automatically later.
Thanks in advance.
You could add a function to the scope to calculate the total at that index. You have to keep in mind that you are using order by which means you should us the as syntax to calculate the value from the ordered list.
CalculatePay function:
$scope.calculatePay = function(index) {
var sum = 0;
for(var i = 0; i <= index; i++) {
sum += parseFloat($scope.orderedList[i].cash);
}
return sum;
};
html:
<table ng-app='Payments'>
<thead>
<tr>
<th>Date</th> <th>Cash</th> <th>Total</th>
</tr>
</thead>
<tbody ng-controller='paymentsController'>
<tr ng-repeat="pay in payments | orderBy: 'date' as orderedList track by pay.id">
<td>{{pay.date}}</td>
<td><input type="textbox" ng-model="pay.cash"/></td>
<td>{{calculatePay($index)}}</td>
</tr>
</tbody>
</table>
track by is also helpful if the id is truely unique
Example: http://plnkr.co/edit/igBGY1h5RIKMNkncxhp6?p=preview
You would need to handle sorting in code, as the orderBy in ng-repeat creates a new list used for the display, and doesn't modify the original list. This would mean that the indexes of items in the display list don't match up with that in the original list. You'll also need a watcher on the payments collection to automatically update the totals at each position.
Something like
$scope.$watch('payments', function(newPayments) {
$scope.payments = orderByFilter($scope.payments, "date");
$scope.total = 0;
angular.forEach($scope.payments, function(payment) {
$scope.total += parseFloat(payment.cash);
payment.total = $scope.total;
});
}, true);
Fiddle: http://jsfiddle.net/29mh8bfe/4/

How to filter a angular table tb if data is == 0

I have 3 different companies a user can be assigned to. A 0 is being displayed in the user.CompanyName if it is Null. How can filter the 0 to not show?
<tr ng-repeat="user in users | filter:search" ng-click="selectUser(user)" style="cursor:pointer">
<td>{{user.CompanyName1 | slug}}<br /> {{user.CompanyName2 | slug}}<br /> {{user.CompanyName3 | slug}} </td>
<td>{{user.Name}}</td>
<td>{{user.UserName}}</td>
<td>{{user.Email}}</td>
</tr>
Slug Filter
app.filter('slug', function () {
return function (input) {
if (input) {
return input.replace(/[_]/g, ' ');
}
};
});
JSON
[
{
"$id":"1",
"Id":"0d286ee5-7408-46dc-9519-1d58e42691d3",
"Name":"Rudy Sanchez",
"UserName":"admin",
"Email":"texa#gmail.com",
"CompanyName1":"Transparent Energy",
"CompanyName2":null,
"CompanyName3":null
}
]

How to have or condition on a ng-repeat

How to have or condition on this repeat ?
I want to filter this tbody depending of a value
MY TABLE
<tbody ng-repeat="Fund in ListTask | filter:{CreationDate: manager.start}:true | filter:{DueDate: manager.end}:true | filter:{Beneficiary: currentNode.name}:true | filter:{Title: currentNode.name}:true | filter:{category: currentNode.name}:true">
<tr ng-dblclick="open(Fund.id)" data-toggle="modal" data-target="{{Fund.type}}">
<td>{{Fund.id}}</td>
<td>{{Fund.Beneficiary}}</td>
<td>{{Fund.Title}}</td>
<td>{{Fund.status}}</td>
<td>{{Fund.category}}</td>
<td>{{FormField.shortDate(Fund.CreationDate)}}</td>
<td>{{FormField.shortDate(Fund.DueDate)}}</td>
<td>{{Fund.Team}}</td>
</tr>
</tbody>
It seems you have to implement your own filter.
Example :
.filter('specialFilter', function() {
return function(funds,manager,currentNode) {
var filtered = [];
angular.forEach(funds, function(fund) {
if (fund.CreationDate ==manager.start|| fund.category==currentNode.name)
filtered.push(fund);
});
return filtered;
};
})
<tbody ng-repeat="Fund in ListTask | specialFilter:manager:currentNode"
To notice, if you have an important number of funds (>2000), it could be better for performances to build yourself a specific array of data filtered.

Resources