Angular (1.x) - Programmatically access NG-REPEAT from code - angularjs

I'm trying to setup hotkeys for an old project that still uses angular 1.x and one of the features I was trying to add would be to select the first row from a table that is created with an NG-REPEAT. I've been able to add in other functionality such has moving the selected row up / down because I pass in the selected row on ng-click="setSelected(this)" which then lets me save the row and move it with selectedRow.$$prevSibiling or selectedRow.$$nextSibiling.
What I'm having a hard time figuring out is how can I set the selectedRow from the controller.
Here is a quick example:
http://plnkr.co/edit/6jPHlYwkgF5raRWt?open=lib%2Fscript.js
JS:
App.controller('ActivitiesCtrl', [function() {
var vm = this;
vm.selectedRow = "Not set";
vm.activities = [
{
"id": 1,
"code": "ABC",
"person": "Joe"
},
{
"id": 2,
"code": "DFF",
"person": "Sally"
},
{
"id": 3,
"code": "ABC",
"person": "Sue"
},
{
"id": 4,
"code": "124",
"person": "Sam"
},
];
vm.setSelected = function(row) {
vm.selectedRow.selected = false;
vm.selectedRow = row;
vm.selectedRow.selected = true;
}
vm.moveNext = function() {
vm.setSelected(vm.selectedRow.$$nextSibling)
}
vm.setFirst = function() {
vm.setSelected("How do I set it...");
// How to set it? vm.setSelected(?????)
}
}]);
HTML:
<div ng-controller="ActivitiesCtrl as vm">
<table>
<thead>
<th>Id</th>
<th>Code</th>
<th>Person</th>
</thead>
<tbody>
<tr ng-repeat="activity in vm.activities track by activity.id" ng-click="vm.setSelected(this)" ng-class="{info: selected}">
<td>{{activity.id}}</td>
<td>{{activity.code}}</td>
<td>{{activity.person}}</td>
</tr>
</tbody>
</table>
{{vm.selectedRow | json}}
<hr />
<button ng-click="vm.setFirst()">Set First</button>
<button ng-click="vm.moveNext()">Next</button>
</div>

You can do this by setting the actual object from the array as selectedRow rather than using this and set the class by checking if selectedRow === activity in the ng-class.
This approach doesn't require mutating the objects
<tr
ng-repeat="activity in vm.activities track by activity.id"
ng-click="vm.setSelected(activity)"
ng-class="{info: vm.selectedRow == activity}"
>
Then you can use Array#findIndex() to get the current selectedRow index in the array and if a next one exists use it or go back to the first.
For the setFirst() you just use vm.activities[0]
vm.selectedRow = null;
vm.setSelected = function (row) {
vm.selectedRow = row;
};
vm.moveNext = function () {
const {selectedRow:curr, activities:act} = vm;
if (curr !== null) {
let idx = act.findIndex(e => e == curr) + 1;
let next = act[idx] || act[0];
vm.setSelected(next);
}
};
vm.setFirst = function () {
vm.setSelected(vm.activities[0]);
};
Working plunker

Here is the link with test working example.
enter code here
http://plnkr.co/edit/7mTvRB0ZlHOQwOIc?preview

Related

Show unique items with count of duplicate occurrences in ng-repeat

I have a below JSON:
[{"brand":"abc"},{"brand":"xyz"},{"brand":"abc"},{"brand":"abc"},{"brand":"por"},{"brand":"xyz"}]
Using ng-repeat, How can I display like -
Brand Occurances
abc (3)
xyz (2)
por (1)
i.e. brand name (number of duplicate occurrences of same brand name)?
You can create a custom function which will be returning the count from the existing array with the repeatvie values (occurances)
Along with the filter to show the unique values from the JSON:
$scope.getCount = function(i) {
var iCount = iCount || 0;
for (var j = 0; j < $scope.brands.length; j++) {
if ($scope.brands[j].brand == i) {
iCount++;
}
}
return iCount;
}
AND a filter will look like this:
app.filter('unique', function() {
return function (arr, field) {
var o = {}, i, l = arr.length, r = [];
for(i=0; i<l;i+=1) {
o[arr[i][field]] = arr[i];
}
for(i in o) {
r.push(o[i]);
}
return r;
};
})
Working Plunkr
To get unique items from an array you could write a custom filter, in AngularJS filters are used to modify the data to be displayed to the user and in order to get the count of the duplicate items from an array you can write a function on the controller's scope and call it in the view.
Check the below code snippet on how to achieve it.
angular
.module('demo', [])
.controller('DefaultController', DefaultController)
.filter('unique', unique);
function DefaultController() {
var vm = this;
vm.items = [
{
"brand":"abc"
},
{
"brand":"xyz"
},
{
"brand":"abc"
},
{
"brand":"abc"
},
{
"brand":"por"
},
{
"brand":"xyz"
}
];
vm.getBrandCount = getBrandCount;
function getBrandCount(brand) {
var count = 0;
if (brand !== undefined && brand !== null && brand.length > 0) {
for (var i = 0; i < vm.items.length; i++) {
if (vm.items[i].brand === brand) {
count++;
}
}
}
return count;
}
}
function unique() {
return function(array, key) {
if (angular.isArray(array) && array.length > 0 && key !== undefined && key !== null && key.length > 0) {
var arr = [], keys = [];
for (var i = 0; i < array.length; i++) {
if (keys.indexOf(array[i][key]) === -1) {
keys.push(array[i][key]);
arr.push(array[i]);
}
}
return arr;
}
return array;
}
}
.brandcount:before {
content: '('
}
.brandcount:after {
content: ')'
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
<table>
<thead>
<tr>
<th>Brand</th>
<th>Occurances</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in ctrl.items | unique: 'brand'">
<td>
<span ng-bind="item.brand"></span>
</td>
<td>
<span class="brandcount" ng-bind="ctrl.getBrandCount(item.brand)"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
You need to first process your data before passing to ng-repeat like this:
var app = angular.module("sa", []);
app.controller("FooController", function($scope) {
var data = [{
"brand": "abc"
}, {
"brand": "xyz"
}, {
"brand": "abc"
}, {
"brand": "abc"
}, {
"brand": "por"
}, {
"brand": "xyz"
}];
$scope.processedData = [];
// Group the raw data based on the brand name and store the count
function groupData() {
angular.forEach(data, function(item) {
// Check https://github.com/sagrawal14/angular-extras/blob/master/src/extras/array.js for this utility "find" method
var existingBrand = $scope.processedData.find("brand", item.brand);
if (!existingBrand) {
existingBrand = item;
existingBrand.count = 0;
$scope.processedData.push(existingBrand);
}
existingBrand.count++;
});
}
groupData();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://rawgit.com/sagrawal14/angular-extras/master/src/extras/array.js"></script>
<div ng-app="sa" ng-controller="FooController">
<table>
<tr ng-repeat="data in processedData">
<td>{{data.brand}}</td>
<td>{{data.count}}</td>
</tr>
</table>
<br><br>Processed/grouped data: {{processedData | json}}
</div>

angularjs filter ng-repeat links outside of list

Building a simple app that filters results based on an input field. I'm adding a bunch of links that are outside of the repeated list and when clicked I want to be able to filter the list below.
I've searched online for various ways of tackling this problem but have yet to find a solution.
I'm already filtering by search, however I'd like to be able to click a link that is a popular search entry.
My code is:
tag one
tag two
tag three
<tr ng-repeat="item in items | orderBy:'date' | filter:itemsFilter" ng-click="clickedItem(item.id)">
<td><img ng-src="{{item.imageUrl}}" alt="{{item.title}}"></td>
<td>
{{item.title}}<br>
</td>
<td><i class="el el-time"></i> {d{item.date}}</td>
<td class="drop-me">{{item.description}}</td>
<td class="tag-me">{{item.tag}}</td>
</tr>
<tr ng-hide="item.length == 0"><td><p>There are no items!</p></td></tr>
I've tried custom filters, just can't figure a way to inject the items via an ng-click and update the list below.
I'd like to click one of the tag links and it filter the list below
Thanks
As proposed in the comments you can create an array to which you're adding your tags for filtering and in a custom filter you can filter your items array.
Also ngTagsInput is a nice directive that's helping to create a input field with tags.
Please have a look at the demo below or this jsfiddle.
angular.module('demoApp', ['ngTagsInput'])
// filter from here (with some modifications) http://stackoverflow.com/questions/23785592/apply-dynamic-filters-using-tags
.filter('filterByTags', function() {
return function(items, tags) {
var filtered = []; // Put here only items that match
(items || []).forEach(function(item) { // Check each item
var matches = tags.some(function(tag) { // If there is some tag
return item.tag == tag.text;
}); // we have a match
if (matches) { // If it matches
filtered.push(item); // put it into the `filtered` array
}
});
return filtered.length == 0 ? items : filtered; // Return the array with items that match any tag // return all if no tags
};
})
.controller('mainController', MainCtrl);
function MainCtrl() {
var vm = this;
function isTagInTags(tag) {
var seen = false;
//console.log('test', tag);
for (var i = 0; i < vm.tags.length; i++) {
//console.log(vm.tags[i].text, tag);
if (vm.tags[i].text == tag) {
seen = true;
return seen;
}
}
return seen;
}
vm.addTag = function(tag) {
//console.log(tag);
if (!isTagInTags(tag)) {
vm.tags.push({
text: tag
});
}
};
vm.data = [{
id: 0,
tag: 'JavaScript',
title: 'this is JS related'
}, {
id: 1,
tag: 'Java',
title: 'this is Java related'
}, {
id: 2,
tag: 'Python',
title: 'this is Python related'
}, {
id: 3,
tag: 'Python',
title: 'also Python stuff...'
}];
var unique = [];
vm.availTags = [];
for (i in vm.data) {
var item = vm.data[i];
//console.log(item);
if (unique.indexOf(item.tag) === -1) {
unique.push(item.tag);
vm.availTags.push(item.tag);
}
}
vm.loadItems = function(query) {
//console.log(query);
return vm.availTags.filter(function(tag) {
var testTag = tag.toLowerCase();
return testTag.indexOf(query.toLowerCase()) >= 0;
});
//return $http.get('/tags?query=' + query); // use this with a backend
}
//console.log(vm.availTags);
vm.tags = []; //vm.availTags[0];
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-tags-input/3.1.1/ng-tags-input.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/ng-tags-input/3.1.1/ng-tags-input.css" rel="stylesheet" />
<div ng-app="demoApp" ng-controller="mainController as ctrl">
<button ng-click="ctrl.addTag('JavaScript')">
JavaScript
</button>
<button ng-click="ctrl.addTag('Java')">
Java
</button>
<!--{{ctrl.tags}}-->
<tags-input ng-model="ctrl.tags">
<auto-complete source="ctrl.loadItems($query)"></auto-complete>
</tags-input>
<div ng-repeat="item in ctrl.data | filterByTags: ctrl.tags">
{{item.title}}
</div>
</div>
try addition ng-href
<a ng-href="">tag one</a>
<a ng-href="">tag two</a>
<a ng-href="">tag three</a>
<tr ng-repeat="item in items | orderBy:'date' | filter:itemsFilter" ng-click="clickedItem(item.id)">
<td><a ng-href="{{item.url}}"><img ng-src="{{item.imageUrl}}" alt="{{item.title}}"></a></td>
<td>
<a ng-href="{{item.url}}">{{item.title}}</a><br>
</td>
<td><i class="el el-time"></i> {d{item.date}}</td>
<td class="drop-me">{{item.description}}</td>
<td class="tag-me">{{item.tag}}</td>
</tr>
<tr ng-hide="item.length == 0"><td><p>There are no items!</p></td></tr>

How to Add a product to the cart and then update the quantity from both the product page and from the cart itself.

I am completely stumped on how to achieve something specific that the below website has achieved. Does anyone know how to update the quantity of a product from the product details page to the shopping cart, and have that quantity shared/bound between the cart and and the product details page for each an every product repeated from a collection. (I am not talking about simply having a global cart quantity total via a simple custom directive). Please see the link below. Add a product to the cart and then update the quantity from both the product page and from the cart itself. This is what I am trying to achieve. Thank you all in advance!
http://demo.shopnx.in/
Typically you'll get better responses if you post some code that you have tried and then ask to be guided on where you are going wrong. I've created a simple JSFiddle to demonstrate one method of doing this. It is extremely simple, contrived, not production worthy by any stretch of the imagination and doesn't really do much, but it should show you one construct that will allow you to accomplish the functionality you're after.
The key is to use some type of shared storage so that the same array of items is available to both your product listing and the cart. In the sample I have done this using a Value:
.value('cartStorage', {
items: []
})
This value is then injected in the main controller:
.controller('mainController', function(cartStorage) {
var _this = this;
_this.cartStorage = cartStorage;
_this.items = [{
name: 'Apple',
price: .5,
quantity: 0,
showAddToCart: false,
addedToCart: false
}, {
name: 'Orange',
price: .5,
quantity: 0,
showAddToCart: false,
addedToCart: false
}, {
name: 'Grapes',
price: 1,
quantity: 0,
showAddToCart: false,
addedToCart: false
}];
_this.addToCart = function(item) {
_this.cartStorage.items.push(item);
item.addedToCart = true;
}
_this.increaseItemAmount = function(item) {
item.quantity++;
item.showAddToCart = true;
}
_this.decreaseItemAmount = function(item) {
item.quantity--;
if (item.quantity <= 0) {
item.quantity = 0;
item.addedToCart = false;
item.showAddToCart = false;
var itemIndex = _this.cartStorage.items.indexOf(item);
if (itemIndex > -1) {
_this.cartStorage.items.splice(itemIndex, 1);
}
} else {
item.showAddToCart = true;
}
}
})
As well as the cart controller:
.controller('cartController', function(cartStorage) {
var _this = this;
_this.cartStorage = cartStorage;
_this.increaseItemAmount = function(item) {
item.quantity++;
}
_this.decreaseItemAmount = function(item) {
item.quantity--;
if (item.quantity <= 0) {
item.quantity = 0;
item.addedToCart = false;
item.showAddToCart = false;
var itemIndex = _this.cartStorage.items.indexOf(item);
if (itemIndex > -1) {
_this.cartStorage.items.splice(itemIndex, 1);
}
}
}
_this.removeFromCart = function(item) {
item.quantity = 0;
item.addedToCart = false;
item.showAddToCart = false;
var itemIndex = _this.cartStorage.items.indexOf(item);
if (itemIndex > -1) {
_this.cartStorage.items.splice(itemIndex, 1);
}
}
})
Now the cartStorage object is shared so any update made in one controller will automagically be reflected in the other controller. All that's left is the markup:
<div ng-app="app">
<div ng-controller="mainController as main">
<h2>Main Controller</h2>
<div>
<table>
<tr>
<td>Item</td>
<td>Price</td>
<td>Quantity</td>
<td></td>
</tr>
<tr ng-repeat="item in main.items">
<td>{{item.name}}</td>
<td>{{item.price | currency}}</td>
<td>{{item.quantity}}</td>
<td>
<button ng-click="main.increaseItemAmount(item)">+</button>
<button ng-click="main.decreaseItemAmount(item)">-</button>
<button ng-click="main.addToCart(item)" ng-show="item.showAddToCart && !item.addedToCart">Add to Cart</button>
</td>
</tr>
</table>
</div>
</div>
<div ng-controller="cartController as cart">
<h2>Cart Controller</h2>
<div>
<table>
<tr>
<td>Item</td>
<td>Price</td>
<td>Quantity</td>
<td></td>
</tr>
<tr ng-repeat="item in cart.cartStorage.items">
<td>{{item.name}}</td>
<td>{{item.price | currency}}</td>
<td>{{item.quantity}}</td>
<td>
<button ng-click="cart.increaseItemAmount(item)">+</button>
<button ng-click="cart.decreaseItemAmount(item)">-</button>
<button ng-click="cart.removeFromCart(item)">Remove from Cart</button>
</td>
</tr>
</table>
</div>
</div>
</div>
Update showing the usage of a Factory instead of Value
Instead of using a Value use this service:
.factory('cartStorage', function() {
var _cart = {
items: []
};
var service = {
get cart() {
return _cart;
}
}
return service;
})
Then modify the code in the controllers to use the .cart property of the service instead of the value. You only need to change one line of code in both controllers. Change:
_this.cartStorage = cartStorage;
to:
_this.cartStorage = cartStorage.cart;
Here is an updated JSFiddle.
I made this plunker as an example.
I've used events to achieve the desired behavior. (
This is just one way of doing this, should have a lot of possibilities)
ProductsController:
app.controller('ProductsCtrl', function($scope, $rootScope) {
$scope.products = [
{
'name': 'Product One',
'price': 10,
'qty': 0
},
{
'name': 'Product two',
'price': 20,
'qty': 0
}
];
// Fire event to add
$scope.add = function(product) {
product.qty++;
$rootScope.$broadcast('addProduct', product.price);
}
// Fire event to remove
$scope.remove = function(product) {
if(product.qty > 0) {
product.qty--;
$rootScope.$broadcast('removeProduct', product.price);
}
}
});
CartController:
app.controller('CartCtrl', function($scope) {
$scope.total = 0;
// Catch the event to add
$scope.$on('addProduct', function(event, data) {
$scope.total += data;
});
// Catch the event to remove
$scope.$on('removeProduct', function(event, data) {
$scope.total -= data;
});
});
View:
<div ng-controller="CartCtrl">Total: {{total}}</div>
<br>
<div ng-controller="ProductsCtrl">
<div ng-repeat="product in products">
<span>Name: {{product.name}}</span>
<br>
<span>Price:{{product.price}}</span>
<span>Quantity:{{product.qty}}</span>
<br>
<button type="button" ng-click="add(product);">Add</button>
<button type="button" ng-click="remove(product);">Remove</button>
<br><br><br>
</div>
</div>
You can have a shared service between your Product details and Cart detail controller which can have an array where you can push the the Product selected with its quantity and other details.

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

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;
};
});

Resources