How to handle 'ng-repeat' together 'ng-model' for individual object.? - angularjs

I have an array with objects with 'SALARY' field. I want to manage 'CREDIT' amount using ng-model. so i am create a function and work fine with object id. but in my case when i am change value of any input field it is change all input's values.
Please any one tell me how to possible change input value only desire input field.
this is my html >
<div ng-repeat="obj in myObj">
{{obj.id}} /
{{obj.name}} /
{{obj.salary}} /
<input type="text" ng-model="credit.amount" />
<button ng-click="updateBalance(obj)">Balance</button>
</div>
and this is my script >
var app = angular.module('myApp',[]);
app.controller('employee', function($scope) {
$scope.myObj = [
{ "id" : 1, "name" : "abc", "salary" : 10000 },
{ "id" : 2, "name" : "xyz", "salary" : 15000 }
]
$scope.credit = {"amount" : 0};
$scope.updateBalance = function(obj){
console.log(obj.name + "'s current balance is : ");
console.log(obj.salary - Number($scope.credit.amount));
}
});
and this is my PLNKR LINK.

Values in all input fields are changing because you are binding $scope.credit.amount to all of them. Instead you need to maintain them separately. Following should work:
Html
<tr ng-repeat="obj in myObj">
<td>{{obj.id}} </td>
<td>{{obj.name}} </td>
<td>{{obj.salary}} </td>
<td>
<input type="number" ng-model="credits[obj.id].amount" />
</td>
<td>
<button ng-click="updateBalance(obj)">Balance</button>
</td>
</tr>
Controller
var app = angular.module('myApp', []);
app.controller('employee', function($scope) {
$scope.myObj = [{
"id": 1,
"name": "abc",
"salary": 10000
}, {
"id": 2,
"name": "xyz",
"salary": 15000
}]
$scope.credits = $scope.myObj.reduce(function(acc, object) {
acc[object.id] = { amount: 0 };
return acc;
}, {});
$scope.updateBalance = function(obj) {
var balance = obj.salary - Number($scope.credits[obj.id].amount)
alert(obj.name + ' balance is : ' + balance);
}
});

Related

Angular JS: How to apply the date range filter between two dates in one column

I am aware that it may be Duplicate Question, but I tried that too but it didnt work it. So, I am posting my Question now. My Question is Apply the Date range filter using Angular js only one column.
Here is MY code:
HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<div>
<table>
<tr>
<td>Start Date</td>
<td><input type="text" name="S_Date" ng-model="startDate"/></td>
<td>End Date</td>
<td><input type="text" name="E_Date" ng-model="endDate"/>
</tr>
</table>
</div>
<table>
<tr>
<th>Date</th>.
<th>Stock</th>
</tr>
<tr ng-repeat="subject in records |myfilter:startDate:endDate">
<td>{{ subject.name * 1000|date:'dd-MM-yyyy'}}<td>
<td>{{ subject.marks }}</td>
</tr>
</table>
Angular JS:
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.records = [
{
"name" : "2016-08-01",
"marks" : 250
},{
"name" : "2016-08-02",
"marks" : 150
},{
"name" : "2016-08-03",
"marks" : 100
},{
"name" : "2016-08-04",
"marks" : 150
},{
"name" : "2016-05-01",
"marks" : 750
},{
"name" : "2016-05-02",
"marks" : 1500
},{
"name" : "2016-03-03",
"marks" : 500
},{
"name" : "2016-04-04",
"marks" : 650
}
]
function parseDate(input) {
var parts = input.split('-');
return new Date(parts[2], parts[1]-1, parts[0]);
}
app.filter("myfilter", function() {
return function(items, from1, to) {
var df = parseDate(from1);
var dt = parseDate(to);
alert(df)
alert(dt)
var result = [];
for (var i=0; i<items.length; i++){
var tf = new Date(items[i].startDate * 1000),
tt = new Date(items[i].endDate * 1000);
if (tf > df && tt < dt) {
result.push(items[i]);
}
}
return result;
};
});
});
</script>
Please advice me Where I am going wrong.Please suggest me.Thanks in advance.
I recommend you to use moment.js library: http://momentjs.com/
Here is working plunkr with your range filter: https://plnkr.co/edit/dfpsBI0uom5ZAEnDF3wM?p=info
<div ng-controller="MainCtrl">
<table>
<tr>
<td>Start Date</td>
<td>
<input type="text" name="S_Date" ng-model="startDate" />
</td>
<td>End Date</td>
<td>
<input type="text" name="E_Date" ng-model="endDate" />
</td>
</tr>
</table>
<table>
<tr>
<th>Date</th>.
<th>Stock</th>
</tr>
<tr ng-repeat="subject in records | myfilter: startDate: endDate">
<td>{{ subject.name | date:'dd-MM-yyyy'}}</td>
<td>{{ subject.marks }}</td>
</tr>
</table>
</div>
app.controller('MainCtrl', function($scope) {
$scope.startDate = "2016-08-01";
$scope.endDate = "2016-08-03";
$scope.records = [{
"name": "2016-08-01",
"marks": 250
}, {
"name": "2016-08-02",
"marks": 150
}, {
"name": "2016-08-03",
"marks": 100
}, {
"name": "2016-08-04",
"marks": 150
}, {
"name": "2016-05-01",
"marks": 750
}, {
"name": "2016-05-02",
"marks": 1500
}, {
"name": "2016-03-03",
"marks": 500
}, {
"name": "2016-04-04",
"marks": 650
}];
});
app.filter("myfilter", function($filter) {
return function(items, from, to) {
return $filter('filter')(items, "name", function(v) {
var date = moment(v);
return date >= moment(from) && date <= moment(to);
});
};
});
$scope.Customfilterobj`enter code here` = { status: "Complete",StartDate: "2017-02-01T08:00:00",EndDate: "2018-02-01T08:00:00 " };
<tr ng-repeat="dt in data | filter: {Status: Customfilterobj.status} | dateRange:Customfilterobj.StartDate:Customfilterobj.EndDate">
Here we have use two filters as below:
filter: {Status: Customfilterobj.status} work as compare "complete" value with Status of data collection.
dateRange:Customfilterobj.StartScheuleDate:Customfilterobj.EndScheuleDate" : dateRange is custom filter for compare Expiration_date between StartDate and EndDate.
app.filter('dateRange', function () {
return function (data, greaterThan, lowerThan) {
if (greaterThan != null && lowerThan != null && greaterThan != undefined && lowerThan != undefined) {
data = data.filter(function (item) {
if (item.Expiration_date != null) {
var exDate = new Date(item.Expiration_date);
return exDate >= new Date(greaterThan) && exDate <= new Date(lowerThan);
}
});
}
return data;
};
});
Adding off of Roman Koliada's plunker. His process has a small issue in the usage of the angular $filter. I have the updated here:
https://plnkr.co/edit/l4t4Fln4HhmZupbmOFki?p=preview
New filter:
app.filter("myfilter", function($filter) {
return function(items, from, to, dateField) {
startDate = moment(from);
endDate = moment(to);
return $filter('filter')(items, function(elem) {
var date = moment(elem[dateField]);
return date >= startDate && date <= endDate;
});
};
});
The issue was that the function input into $filter function was the third param, and loops over every attribute of every object in the list. Console logging his plunker calls moment() on every single attribute of every object. By instead inputting a function as the second param, as the expression instead of the comparator - we can call the comparison only on the date field.
Angular doc: https://docs.angularjs.org/api/ng/filter/filter

orderBy dd/mm/yyyy by year angular

The data I am receiving from a webservice is formatted as dd/mm/yyyy. The problem with this is when sorting, it sorts by dd rather than yyyy.
<td ng-repeat="thead in resultHeader">
{{thead.head}}
<span class="sortorder" ng-show="predicate === thead.line" ng-class="{reverse:reverse}"></span>
</td>
Controller:
$scope.order = function(predicate) {
var results = $scope.model.resultList;
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
$scope.predicate = predicate;
$scope.model.currentPage = 1;
$scope.model.beginFrom = 0;
};
How can I sort this data by yyyy with my current set up?
{
"name": "Test",
"ShipmentDate": "06\/08\/2012"
}
The key part is to add a $filter to your module and use that $filter to get the Date value from the string. you can use Date.parse('dd/mm/yyyy') to get the time in float, and then run an Array.sort() to your data.
If you converted your date strings to Date objects, you can use the orderBy: filter to sort by date.
<td ng-repeat="thead in resultHeader | orderBy:'ShipmentDate':shouldBeReversedOrder ">
{{thead.head}}
<span class="sortorder" ng-show="predicate === thead.line" ng-class="{reverse:reverse}"></span>
</td>
When you want to display the date back in a proper formate you can use {{thead.ShipmentDate | 'yyyy-mm-dd'}} to format it for you.
Use the custom order for this. Look:
function MyCtrl($scope, orderByFilter) {
$scope.sortedFriends = [
{
name: 'John',
age: 25,
dateTest: '10/10/2015'
}, {
name: 'Jimmy',
age: 25,
dateTest: '10/12/2015'
},{
name: 'Mary',
age: 28,
dateTest: '10/09/2009'
}, {
name: 'Ed',
age: 27,
dateTest: '30/03/2014'
},{
name: 'Andrew',
age: 27,
dateTest: '11/11/2016'
}];
$scope.orderByCustom = function(friend) {
console.log(friend)
return friend.dateTest.split('/')[2];
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat="friend in sortedFriends | orderBy:orderByCustom"">
{{friend}}
</li>
</ul>
</div>

Angularjs checkbox multiple filter

I have factory, that send request to get some data. After responce, i will receive it in controller and create scope list. Than i must to filter this list by checking checkboxes. I'v receive results, but they not visible. Help me pls...
$scope.checkRooms = [];
$scope.filterRooms = function(app) {
return function(p) {
for (var i in $scope.checkRooms) {
if (p.rooms == $scope.uniqueRooms[i] && $scope.checkRooms[i]) {
return true;
}
}
};
};
UPDATE 2
Here is working fiddle . Now how to sort by ASC rooms numbers? "orderBy" function sort correct but rooms indexes sort wrong
Ok here's a slightly different approach whereby the filtering is done in the controller rather than using the filter:expression in your ng-repeat.
Not the only way to do it but I think you should definitely think about removing any watch functions from your controllers they make it really difficult to test your controllers.
Fiddle
HTML
<div class="filter-wrap" ng-controller="mainController">
<div class="main-filter">
<div class="form-group">
<span class="gr-head">
Rooms count
</span>
<div class="check-control" ng-repeat="room in uniqueRooms | orderBy: room">
<input
type="checkbox"
name="room_cnt"
ng-model="checkboxes[room]"
ng-change='onChecked(filterRoom)'
/>
<label>{{room}}</label>
</div>
</div>
</div>
<table>
<thead>
<tr>
<th>
<span>Rooms</span>
</th>
<th>
<span>Size</span>
</th>
<th>
<span>Price</span>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="app in filteredApps">
<td>{{app.rooms}}</td>
<td>{{app.size}}</td>
<td>{{app.price}}</td>
</tr>
</tbody>
</table>
<div class="result">
<h2>SCOPE size</h2>
{{filteredRooms}}
</div>
</div>
JS
var sortApp = angular.module('sortApp',[]);
sortApp.controller('mainController', function($scope, $timeout) {
$scope.apps = [
{
"rooms": 2,
"size": 55.50,
"price": 55500.00,
},
{
"rooms": 1,
"size": 25.50,
"price": 45000.00,
},
{
"rooms": 8,
"size": 28,
"price": 15500.00,
},
{
"rooms": 1,
"size": 28,
"price": 15500.00,
},
{
"rooms": 8,
"size": 28,
"price": 15500.00,
},
{
"rooms": 3,
"size": 120.55,
"price": 88990.00,
},
{
"rooms": 3,
"size": 120.55,
"price": 88990.00,
}
];
$scope.filteredApps = $scope.apps;
$scope.uniqueRooms = uniqueItems($scope.apps, 'rooms');
$scope.onChecked = filterRooms;
$scope.checkboxes = createCheckboxes($scope.uniqueRooms);
function filterRooms(checkboxes){
$scope.filteredApps = [];
angular.forEach($scope.apps, function(app){
if($scope.checkboxes[app.rooms]){
$scope.filteredApps.push(app);
}
});
}
function createCheckboxes(labels){
var checkboxes = {};
angular.forEach(labels, function(label){
checkboxes[label] = true;
});
return checkboxes;
}
function uniqueItems(data, key) {
var result = [];
for (var i = 0; i < data.length; i++) {
var value = data[i][key];
if (result.indexOf(value) == -1) {
result.push(value);
}
}
return result;
};
});

ng-options inside ng-repeat (with similar looking object) unexpected behavior, weird behavior

This is my first ever stackoverflow question therefore some help will be highly appreciated. I am working on an angular application where on one ui section, user is given a chance to multiple different choices which can be duplicate. e.g
A list of devices from the list. User can create multiple and they can even be all same types.
Working fiddle:
http://jsfiddle.net/mrafaqi/dpLd85ep/5/
<table id="devices-table" class="table">
<tr ng-repeat="item in requiredDevices track by $index" height="30">
<td>
<select
id="deviceList_{{$index}}"
name="deviceList_name_{{$index}}"
ng-model="item"
ng-options="d.name for d in devices track by d.id"
ng-change="deviceChanged($index, item)"
>{{item}}
</select>
<div id="device-options" ng-show="item.id > -1">
<label for="all_{{$index}}">1. Choose all</label><input id="all_{{$index}}" type="radio" name="type_{{$index}}" value="1" ng-model="item.amountType" checked><br>
<label for="some_{{$index}}">2. Choose some</label><input id="some_{{$index}}" type="radio" name="type_{{$index}}" value="2" ng-model="item.amountType" ><br>
<label for="amount_{{$index}}">3. Choose amount</label><input id="amount_{{$index}}" type="radio" name="type_{{$index}}" value="3" ng-model="item.amountType" ><br>
</div>
<br>
</td>
</tr>
<tr id="add-device">
<td>
<br>
<button id="add-device-button" ng-click="addDevice();">Add more</button>
<button id="add-device-button" ng-click="showRequiredDevices();">Show required devices</button>
</td>
</tr>
</table>
The corresponding javascript for this code is
var new_test_controller = app.controller('new_test_controller', function($scope) {
$scope.init = function() {
$scope.current_customer = $scope.customers[0].first_name;
$scope.addDevice();
};
$scope.test1_text = "";
$scope.customers =
[
{ "uid": 1, "first_name": "Rizwan", "last_name": "Zia" },
{ "uid": 2, "first_name": "Laura", "last_name": "Zia" },
{ "uid": 3, "first_name": "Sara", "last_name": "Zia" },
];
$scope.devices = [
{"id" : 1, "name": "scissors", "amount": 3, "amountType": -1},
{"id" : 2, "name": "jumppapallo", "amount": 3, "amountType": -1},
{"id" : 3, "name": "gymstick", "amount": 3, "amountType": -1},
];
$scope.requiredDevices = [
];
$scope.addDevice = function() {
var device = new Object();
device.tid = $scope.requiredDevices.length;
device.id = -1;
device.name = "";
device.amount = 0;
device.amountType = -1;
console.log(device);
$scope.requiredDevices.push(device);
};
$scope.showRequiredDevices = function() {
console.log($scope.requiredDevices);
};
$scope.deviceChanged = function($index, item) {
console.log('Device changed at index: ' + $index);
console.log(item);
//$scope.requiredDevices[$index] = item;
};
//console.log('Controller must have been initialized');
$scope.init();
});
Now, the problem is that I can't choose same devices with different attributes. To generate this behavior
Click add more button twice or more (create at least 2 devices)
Choose gymstick in first and second combo box
Choose any other device in third combo box
Now if you try to click radio button for gymstick, it will update the value of the other item as well which I do not want. It seems to be some behavior of angular. I tried to use $index (t.id was try to hack it). Any help will be greatly appreciated :)
There is a conflict between two item variable
item in ng-repeat.
item model in select box
you can change the select box model
ex :
<select
id="deviceList_{{$index}}"
name="deviceList_name_{{$index}}"
ng-model="item1"
....
</select>
and change ng-show to
<div id="device-options" ng-show="item1.id > -1">
here is the Demo Fiddle

how can I add groups under an active/inactive child?

I have successfully been able to send data to the firebase server however I am having trouble getting the data to send to the appropriate data subset I have created. When I send data made in the html form, It sends organized by ID number. I need it to be sent as a child to the 'groups' category in firebase.
here is a Plnkr with the server and $add working. Any suggestions I would really appreciate!
http://plnkr.co/edit/LZ24sRoSJjuCHQnEGzQz?p=linter
.controller('MainCtrl', ['$scope', 'groupsService', function( $scope, groupsService, $firebase ) {
$scope.newGroup = {
name: '',
status: ''
};
$scope.addGroup = function(newGroup) {
groupsService.addGroup(newGroup);
$scope.newGroup = {
name: '',
status: ''
};
};
$scope.updateGroup = function (id) {
groupsService.updateGroup(id);
};
$scope.removeGroup = function(id) {
groupsService.removeGroup(id);
};
}])
.factory('groupsService', ['$firebase', 'FIREBASE_URI',
function ($firebase, FIREBASE_URI) {
var ref = new Firebase(FIREBASE_URI);
var groups = $firebase(ref).$asArray();
var getGroups = function(){
return groups;
};
var addGroup = function (newGroup) {
console.log(newGroup)
groups.$add(newGroup);
};
var updateGroup = function (id){
groups.$save(id);
};
var removeGroup = function (id) {
groups.$remove(id);
};
return {
getGroups: getGroups,
addGroup: addGroup,
updateGroup: updateGroup,
removeGroup: removeGroup,
}
}]);
Thanks for responding! What I am trying to do is add dummy data (name and status) to the groups category like this:
{
Groups:[
"-JcFXid1A2G8EM7A_kwc" : {
"name" : "hi",
"status": "inactive"
},
"-JcFZP5FNtL4Yj6nja_7" : {
"name" : "hi"
"status": "inactive"
},
"-JcFtGoZL7J-CCIjTYcL" : {
"name" : "dfgdfg",
"status": "inactive"
}
]
}
would it make more sense to have them organized by active or inactive? I am afraid to nest too far in firebase...
like
{
Groups:[
"Active":[
"-JcFXid1A2G8EM7A_kwc" : {
"name" : "hi",
}
],
"Inactive":[
"-JcFZP5FNtL4Yj6nja_7" : {
"name" : "hi"
},
"-JcFtGoZL7J-CCIjTYcL" : {
"name" : "dfgdfg"
}
]
]
}
This isn't an answer to your question yet, because I first need to understand what you're trying to accomplish (and I can't fit this amount of information in a comment).
In your view you have a form that binds to the group's name and status:
<form role="form" ng-controller="MainCtrl" ng-submit="addGroup(newGroup)">
<div class="form-group">
<label for="groupName">Group Name</label>
<input type="text" class="form-control" id="groupName" ng-model="newGroup.name">
</div>
<div class="form-group">
<label for="groupStatus">Group Status</label>
<select class="form-control" ng-model="newGroup.status">
<option value="inactive">Inactive</option>
<option value="active">Active</option>
</select>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
In your GroupsService you essentially add a group like this:
var ref = new Firebase(FIREBASE_URI);
var groups = $firebase(ref).$asArray();
groups.$add(newGroup);
Which adds the group to the collection at that URL.
Which leads to this data structure:
{
"-JcFXid1A2G8EM7A_kwc" : {
"name" : "hi",
"status" : "inactive"
},
"-JcFZP5FNtL4Yj6nja_7" : {
"name" : "hi",
"status" : "active"
},
"-JcFtGoZL7J-CCIjTYcL" : {
"name" : "dfgdfg",
"status" : "active"
}
}
But if I understand you correctly you to want the data to be stored like this:
{
"inactive": [
"-JcFXid1A2G8EM7A_kwc" : {
"name" : "hi"
}
],
"active": [
"-JcFZP5FNtL4Yj6nja_7" : {
"name" : "hi"
},
"-JcFtGoZL7J-CCIjTYcL" : {
"name" : "dfgdfg",
}
]
}
Is this indeed what you're looking to do?
Are you ever going to display active and inactive groups combined in a list? This is important to know, since it is quite easy to filter a list in Angular, but I wouldn't know how to merge two lists.

Resources