Angularjs ng-repeat sum the fields - angularjs

Hi I am new to angularjs I have a problem in calculation the sum of the field my code is like this
<div ng-repeat="(key,item) in expenses_data | groupBy: 'category_name'">
<h4 ng-cloak><i class="fa fa-plus-circle"></i> {{ key }}</h4>
<div class="form-group" ng-repeat="expn_head in item">
<label class="col-sm-3 control-label">{{ expn_head.name }}</label>
<div class="col-sm-2">
<input type="text" class="form-control input-sm" ng-model="expenses.expenditure_head[expn_head.id]">
</div>
</div>
</div>
How do I sum up all the expenses.expenditure_head value entered and put it in the new text field. Is there any function like this:
<input type=text ng-value="{{ sum() }}">
and js
$scope.sum = function() {
var total = 0;
for (var i = 0; i < $scope.expenses.expenditure_head; i++) {
var myValue = $expenses.expenditure_head[i];
total += myValue;
}
return total;
}
json
[
{
"id":23,
"name":"Agency Commission",
"expenditure_category_id":1,
"category_name":"Main"
},
{
"id":22,
"name":"Bonus to Local Staff",
"expenditure_category_id":1,
"category_name":"Main"
},
{
"id":48,
"name":"Advance for Expenses",
"expenditure_category_id":2,
"category_name":"Other Dept's Budget Exp"
},
{
"id":49,
"name":"Agency TDS",
"expenditure_category_id":2,
"category_name":"Other Dept's Budget Exp"
}
]
Can anyone show me the right direction? I have trying this for a day.

The right way is to do so inside the controller. Create a function call it getSum()
$scope.getSum = function(){
var total = 0;
for(var i = 0; i < $scope.someVar; i++){
var myValue = $someVar[i];
sum += myValue;
}
return sum;
};
Then inside your code you do something like
<td>Total: {{ getSum() }}</td>

Related

Datetime range custom filter not working

I am trying to filter a list by time frame. I am using angularjs, bootstrap datetimepicker and moment.js. But what happens is I am not able to list the data. Without the custom filter I am able show the list and also do simple text filter search. I have added the code related to custom filter.
Code related to filter in Controller
App.controller('ReportController', ['$scope', 'Report','$filter', function($scope, Report,
$filter){
var self = this;
$filter('myfilter')(dateFrom ,dateTo);
App.filter('myfilter', function() {
return function(items, from, to) {
var result = [];
for (var i=0; i<items.length; i++){
var test = new Date(items[i].dateTime.$date);
var month = test.getMonth()+1;
var date = test.getDate();
var year = test.getFullYear();
var hour = test.getHours();
var minute = test.getMinutes();
var second = test.getSeconds();
var newDate = year+"-"+month+"-"+date+""+hour+"-"+minute+"-"+second;
if (newDate > from && newDate < to) {
result.push(items[i]);
}
}
return result;
};
});
}]);
In Html
<div ng-show="Sradioption == 'showSearch2'" class='input-group date' id='datetimepicker6'>
<input type='text' ng-model="dateFrom" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
<div ng-show="Sradioption == 'showSearch2'" class='input-group date' id='datetimepicker7'>
<input type='text' ng-model="dateTo" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>C_Number</th>
<th>Datetime</th>
<th>Reading</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="r in ctrl.reports | filter:search | myfilter:dateFrom:dateTo">
<td>{{r.c_Number}}</td>
<td>{{r.dateTime}}</td>
<td>{{r.reading}}</td>
</tr>
</tbody>
</table>
You need to take out the filter out of your controller,
App.filter('myfilter', function() {
return function(items, from, to) {
var result = [];
for (var i = 0; i < items.length; i++) {
var test = new Date(items[i].dateTime.$date);
var month = test.getMonth() + 1;
var date = test.getDate();
var year = test.getFullYear();
var hour = test.getHours();
var minute = test.getMinutes();
var second = test.getSeconds();
var newDate = year + "-" + month + "-" + date + "" + hour + "-" + minute + "-" + second;
if (newDate > from && newDate < to) {
result.push(items[i]);
}
}
return result;
};
});

Cross check input check box values against an array in angular

I have an array like following in my controller:
$scope.word_pair = [
{'word':'Carla', 'pair':'Lion'},
{'word':'Sophie', 'pair':'Lotta'},
{'word':'Jannes', 'pair':'Stubbi'},
{'word':'Martin', 'pair':'Wolle'},
{'word':'Flo', 'pair':'Ign'},
{'word':'Rere', 'pair':'Rose'},
{'word':'Jean', 'pair':'Tamara'},
{'word':'Memo', 'pair':'Elk'},
{'word':'Nila', 'pair':'Naph'}
]
On my HTML template I have two input lists wherein I am supposed to enter few of the combinations from above array and if the combination is correct then there will be a green checkmark.
My HTML looks like following as of now:
<!-- Level 2 Enter view for words for corresponding pairs -->
<div class="col col-50" ng-if="enterTextViewLeft">enterTextViewLeft
<ion-list>
<ion-item ng-repeat="item in randomWord_pair" id="list_two">
<input placeholder="Type here" ng-model="word" type="text" ng-change="leftPartnerCheck(word,item.pair)">
<div ng-show="showPartner[word]" align="right"><i class="ion-checkmark myCheckmark"></i></div>
</ion-item>
</ion-list>
</div>
<!-- Level 1 Enter view for pairs for corresponding words -->
<div class="col col-50" ng-if="enterTextViewRight">enterTextViewRight
<ion-list>
<ion-item ng-repeat="item in randomWord_pair" id="list_two">
<input placeholder="Type here" ng-model="pair" type="text" ng-change="rightPartnerCheck(pair,item.word)">
<div ng-show="showPartner[pair]" align="right"><i class="ion-checkmark myCheckmark"></i></div>
</ion-item>
</ion-list>
</div>
Screenshot of how it actually looks (this is from level 1 of the game, for level 6 instead of word list in left side, input list will be there too, so basically left and right input list to fill in any combination from above array in any order):
UPDATE:
I have couple of functions as well:
$scope.rightPartnerCheckList = {};
for(var v in $scope.randomWord_pair){
$scope.expectedPairSequece.push($scope.randomWord_pair[v].pair)
$scope.rightPartnerCheckList[$scope.randomWord_pair[v].word] = $scope.randomWord_pair[v].pair;
}
$scope.leftPartnerCheckList = {};
for(var v in $scope.randomWord_pair){
$scope.expectedWordSequece.push($scope.randomWord_pair[v].word)
$scope.leftPartnerCheckList[$scope.randomWord_pair[v].pair] = $scope.randomWord_pair[v].word;
}
$scope.showPartner = {};
$scope.rightPartnerCheck = function(p,i_p){
if($scope.rightPartnerCheckList[i_p] == p){
$scope.showPartner[p] = true;
if($scope.enteredSequence.indexOf(p)==-1){
$scope.enteredSequence.push(p)
}
}
}
$scope.leftPartnerCheck = function(w,i_w){
if($scope.leftPartnerCheckList[i_w] == w){
$scope.showPartner[w] = true;
if($scope.enteredSequence.indexOf(w)==-1){
$scope.enteredSequence.push(w)
}
}
}
How can I implement such a logic (for two input lists and checking for existing combinations in array) or incorporate in my existing logic?
I have created an example of how to do this and I will explain below:
HTML:
<div ng-controller="MyCtrl">
<table>
<tr ng-repeat="w in word_pair">
<td> <input type="text" ng-model="guesses[$index]"> </td>
<td> <input type="text" ng-model="otherguesses[$index]"> </div> </td>
<td> <input type="checkbox" ng-checked="check(guesses[$index], otherguesses[$index])" disabled> </td>
</tr>
</table>
</div>
AngularJS:
$scope.word_pair = [
{'word':'Carla', 'pair':'Lion'},
{'word':'Sophie', 'pair':'Lotta'},
{'word':'Jannes', 'pair':'Stubbi'},
{'word':'Martin', 'pair':'Wolle'},
{'word':'Flo', 'pair':'Ign'},
{'word':'Rere', 'pair':'Rose'},
{'word':'Jean', 'pair':'Tamara'},
{'word':'Memo', 'pair':'Elk'},
{'word':'Nila', 'pair':'Naph'}
];
$scope.guesses = [];
$scope.otherguesses = [];
$scope.check = function(word, pair) {
for(var i=0; i<$scope.word_pair.length; i++) {
if($scope.word_pair[i].word == word && $scope.word_pair[i].pair == pair) {
return true;
}
}
}
Use ng-repeat for every object inside the array word_pair
Create inputs and checkbox for each object
Create an arrays ($scope.guesses and $scope.otheruesses) and store the user input there (ng-model="guesses[$index]" and ng-model="otherguesses[$index]")
$index is the current index of ng-repeat which is associated with the index inside word_pair
Check if they match (check(guesses[$index], otherguesses[$index]))
You can check for duplicates inside check if you wish.
CodePen: http://codepen.io/theblindprophet/pen/zBRNmN

Cart calculations in AngularJS

I'm just starting out with AngularJS attempting to build a shopping cart.
Below is my code.
Items.html
<li id="{{item.id}}" ng-click="addItem(item)" class="menu-item" ng-repeat="item in items">
<span class="list-item-inner">
<span class="item-content">
<span class="vc-outer">
<span class="vc-inner">
<span class="list-item-title" style="color: #3F4B56; font-size: 1.1rem;"
ng-bind="item.name">
</span>
<span class="list-item-description" style="font-size: 0.9rem; color: #6B7781;" ng-bind="item.description">
</span>
</span>
</span>
</span>
</span>
<span class="item-price">
<span class="vc-outer">
<span class="vc-inner no-wrap"
ng-bind="'₦' + (item.price)"></span>
</span>
</span>
<span class="item-add"></span>
</li>
Cart.html
<li class="has-counter order-item" ng-class="{'has-modifier' : cart.length}" ng-repeat="item in cart">
<div class="counter-control-vertical is-editable">
<div class="controls"> <a href="" class="control ctrl-up" ng-click="incQty(item)" style="text-decoration: none;">
+
</a>
<a href="" class="control ctrl-down" ng-click="decQty(item)" style="text-decoration: none;">
–
</a>
</div>
</div>
<div class="oi-inner">
<div class="oi-details" ng-click="editModifiers(item)">
<div class="oi-quantity" ng-bind="(item.count) +'x'"></div>
<div class="oi-title" ng-bind="item.name"></div>
<div class="oi-modifiers"></div>
</div>
<div class="oi-price" ng-bind="'₦' + (item.price)"></div> ×
</div>
</li>
Cart.js
// Array containing my items.
$scope.itemData = <? php echo json_encode($item_array); ?> ;
$scope.cart = [];
$scope.deleteItem = function (item) {
var cart = $scope.cart;
var match = getMatchedCartItem(item);
if (match.count > 0) {
cart.splice(cart.indexOf(item));
return;
}
}
$scope.addItem = function (item) {
var match = getMatchedCartItem(item);
if (match) {
match.count += 1;
return;
}
var itemToAdd = angular.copy(item);
itemToAdd.count = 1;
$scope.cart.push(itemToAdd);
}
$scope.incQty = function (item) {
var match = getMatchedCartItem(item);
if (match) {
match.count += 1;
return;
}
}
$scope.decQty = function (item) {
var cart = $scope.cart;
var match = getMatchedCartItem(item);
if (match.count > 1) {
match.count -= 1;
return;
}
cart.splice(cart.indexOf(item), 1);
}
At the moment I can add, remove, increment and decrement items in the cart array and display them in realtime. But the price does not change based on qty.
My question is;
How can I calculate and display price based on qty of an item in cart?
How do I calculate total price of all the items in the cart array?
ng-bind="item.price * item.count"
I would call a function (witch calculates the total price) every time you change the cart and store the result in an new variable.
$scope.calcTotal = function() {
var total=0;
for (var i = 0, max = $scope.cart.length; i < max; i++) {
total += $scope.cart[i].price * $scope.cart[i].count;
}
$scope.total = total;
}

angular js checkbox and select dynamic binding to give total price

I have a working code that gives the sum of the total item in a json file after ticking one or all of the checkboxes
Here is my controller
$scope.testFood = [{ name: item1, price: 400 }, { name: item2, price: 800 }, { name: item3, price: 1000 }];
$scope.selectedItems = [];
$scope.value = function (isSelected, item) {
if (isSelected == true) {
$scope.selectedItems.push(item);
} else {
// console.log(item.name);
angular.forEach($scope.selectedItems, function (itemRmv, $index) {
if (itemRmv.itemid == item.itemid) {
$scope.selectedItems.splice($index, 1);
}
})
}
console.log($scope.selectedItems);
}
The filter:
.filter('getprice', function () {
return function (value, property) {
var total = 0;
angular.forEach(value, function (val, index) {
total = total + Number(val.price)
});
return total.toFixed(2);
}
});
The html template:
<ul class="list" ng-repeat ="item in testFood">
<li class="item item-checkbox">
<label class="checkbox">
<input type="checkbox" ng-model="item.isSelected" ng-change="value(item.isSelected,item)">
</label>
{{item.package_name}} <p>N {{item.price}}</p>
</li> X
<label class="item item-input">
<input type="number" value="0" min="0" step="1">
</label>
</ul>
Calling {{selectedItems | getprice}} gives the total price.
I want the quantity for each product to be calculated along side the total price, how do I do that?
Thanks.

Angularjs - How to check for unique inputs and if there is a duplicate mark both as invalid

I have a situation where a user needs to enter input into text areas created by ng-repeat.
If the user enters a value that has already been entered both the new and existing values should be validated as false. If one of the values (existing or new) gets changed, the validation should be updated correspondingly.
I have tried quite a variety of options, currently this is what comes close, but is still not 100%.
HTML:
<body ng-app="ap" ng-controller="con">
<table>
<tr>
<td>name</td>
</tr>
<tr ng-repeat="person in persons">
<td>
<ng-form name="personForm">
<div ng-class="{ 'has-error' :
personForm.personName.$invalid }">
<input type='text'
name="personName"
ng-class="empty"
ng-model="person.name"
ng-change="verifyDuplicate(this, person)"/>
</div>
</ng-form>
</td>
</tr>
</table>
JavaScript:
var app = angular.module("ap",[]);
app.controller("con",function($scope){
$scope.persons = [
{name: 'a'},
{name: 'b'},
{name: 'c'}
];
$scope.empty = "normal";
$scope.verifyDuplicate = function(domScope, object){
for(var i = 0; i < $scope.persons.length; i++) {
if($scope.persons[i].name === object.name && $scope.persons[i] !== object) {
domScope.personForm.personName.$setValidity('duplicate',false);
}
else {
domScope.personForm.personName.$setValidity('duplicate',true);
}
}
};
});
Any help on this would be appreciated.
Here is a fiddle Fiddle of code
I think it might because the verifyDuplicate method keeps setting and re-setting the validity of the same model, so the validity of the model triggering method invocation will be based on the last comparison result in the loop.
One way to solve this is to let the verifyDuplicate method work on the persons collection as a whole, no matter which model change triggers the method invocation, in this example the $setValidity method is not used, instead, a isDuplicate property on the model is set to indicate duplication.
HTML:
<ng-form name="personForm">
<div ng-class="{ 'has-error' :
personForm.personName.$invalid }">
<input type='number'
name="personName"
ng-class="empty"
ng-model="person.name"
ng-change="verifyDuplicate()"/>
</div>
</ng-form>
<div class='error'
ng-if='person.isDuplicate'>
Duplicate.
</div>
JavaScript:
$scope.verifyDuplicate = function() {
var sorted, i;
sorted = $scope.persons.concat().sort(function (a, b) {
if (a.name > b.name) return 1;
if (a.name < b.name) return -1;
return 0;
});
for(i = 0; i < $scope.persons.length; i++) {
sorted[i].isDuplicate = ((sorted[i-1] && sorted[i-1].name == sorted[i].name) || (sorted[i+1] && sorted[i+1].name == sorted[i].name));
}
};
JSFiddler: http://jsfiddle.net/luislee818/pkhxkozp/4/
If we insist using $setValidity, I can think of connecting individual model to its form with "ng-init" directive, however this looks cumbersome and there might be better ways if we go with this approach.
HTML:
<ng-form name="personForm">
<div ng-class="{ 'has-error' :
personForm.personName.$invalid }">
<input type='number'
name="personName"
ng-init="person.form = personForm"
ng-class="empty"
ng-model="person.name"
ng-change="verifyDuplicate()"/>
</div>
</ng-form>
<div class='error'
ng-show=
'personForm.personName.$error.duplicate'>
Duplicate.
</div>
JavaScript:
$scope.verifyDuplicate = function() {
var sorted, i, isDuplicate;
sorted = $scope.persons.concat().sort(function (a, b) {
if (a.name > b.name) return 1;
if (a.name < b.name) return -1;
return 0;
});
for(i = 0; i < $scope.persons.length; i++) {
isDuplicate = ((sorted[i-1] && sorted[i-1].name == sorted[i].name) || (sorted[i+1] && sorted[i+1].name == sorted[i].name));
sorted[i].form.personName.$setValidity('duplicate',!isDuplicate);
}
};
JSFiddle: http://jsfiddle.net/luislee818/nzd87f1s/1/

Resources