Order 1st ng-repeat by the 2nd ng-repeat value - javascript

Lets say I have two ng-repeats like
<div ng-repeat="category in categories">
{{category.name}}
<div ng-repeat="subcategory in category.subcategories">
{{subcategory.value}}
</div>
</div>
and I've would like to order the categories according to the subcategory.value?
JS:
$scope.categories = [
{
name: "1st category",
subcategories: [
{
name: "1st subcategory",
value: 1
},
{
name: "2nd subcategory",
value: 2
}
]
},
{
name: "2nd category",
subcategories: [
{
name: "3rd subcategory",
value: 5
},
{
name: "4th subcategory",
value: 6
}
]
},
{
name: "3rd category",
subcategories: [
{
name: "4th subcategory",
value: 3
},
{
name: "5th subcategory",
value: 4
}
]
}
];
Also made a Plunker:
https://plnkr.co/edit/8ugJckYRrZoyQlnBYkuU
Expected result should be:
2nd category
6
5
3rd category
4
3
1st category
2
1

Solved it by creating a customOrderBy.
HTML:
<div ng-repeat="category in categories | customOrderBy:'subcategories':'value':true">
JS:
.filter('customOrderBy', function() {
return function(items, field, value, reverse) {
var filtered = [];
angular.forEach(items, function(item) {
item.subcategories.sort(function(a, b){
return a[value]-b[value];
});
if(reverse) item.subcategories.reverse();
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field][0][value] > b[field][0][value] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
});
Here's the Plunker: https://plnkr.co/edit/8ugJckYRrZoyQlnBYkuU?p=preview

Below this code:
<div ng-repeat="category in categories | orderBy:'name':true">
{{category.name}}
<div ng-repeat="subcategory in category.subcategories | orderBy: 'value':true">
{{subcategory.value}}
</div>
</div>

For your expected result:
<div ng-repeat="category in categories | orderBy: '-name'">
{{category.name}}
<div ng-repeat="subcategory in category.subcategories | orderBy: '-value'">
{{subcategory.value}}
</div>
</div>
https://plnkr.co/edit/t3UVFpb3TLGAQdYMIbbd?p=preview

Related

Multi level json filter in angular js

I am new in angular js i want to put filter in ng-repeat i have json like this
var data = [
{name:test1,b1:{lastValue:0},b2:{lastValue:6},b3:{lastValue:6},b4:{lastValue:0}}
{name:test2,b1:{lastValue:6},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
{name:test3,b1:{lastValue:6},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
]
I want to put filter on lastValue i tested like this
ng-repeat = "d in data | filter:{*.lastValue:filterStatus}"
filterStatus // contain value of filter which user selected but its not working
I don't know how to do this i tried google but nothing found please help me
<input ng-model="filterStatus" type="text">
your filterStatus should hold model value
ng-repeat = "d in data | filter:filterStatus"
var app = angular.module("Profile", []);
app.controller("ProfileCtrl", function($scope) {
$scope.filter_val = {}
$scope.data = [{
name: 'test1',
b1: {
lastValue: 0
},
index: 'b1'
}, {
name: 'test2',
b2: {
lastValue: 6
},
index: 'b2'
}, {
name: 'test3',
b3: {
lastValue: 6
},
index: 'b3'
}, {
name: 'test4',
b4: {
lastValue: 0
},
index: 'b4'
}, {
name: 'test5',
b5: {
lastValue: 89
},
index: 'b5'
}, {
name: 'test6',
b6: {
lastValue: 68
},
index: 'b6'
}]
$scope.own_filter = function(val) {
if (!$scope.filter_val.value)
return true;
else {
return (String(val[val['index']]['lastValue'] || '').indexOf($scope.filter_val.value) != -1)
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="Profile" ng-controller="ProfileCtrl">
<input type="text" ng-model="filter_val.value" placeholder="Enter Last Value">
<div class="row" ng-repeat="event in data |filter:own_filter track by $index ">
<h4>{{'Name : ' + event.name}}------{{'Last Value : '+event[event['index']]['lastValue']}}</h4>
</div>
</body>
Use {$:filterStatus} construction:
angular.module('app', []).controller('ctrl',function($scope){
$scope.data = [
{name:'test1',b1:{lastValue:1},b2:{lastValue:6},b3:{lastValue:6},b4:{lastValue:0}},
{name:'test2',b1:{lastValue:2},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}},
{name:'test3',b1:{lastValue:3},b2:{lastValue:0},b3:{lastValue:6},b4:{lastValue:0}}
]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<div ng-app='app' ng-controller='ctrl'>
<input type='number' ng-model='filterStatus' ng-init='filterStatus=1'>
<ul>
<li ng-repeat='item in data | filter: {$:filterStatus}'>{{item.name}}</li>
</ul>
</div>

Hide Empty Filtered ng-repeat

I am looking to hide a category if it it empty. My current solution is not working:
HTML:
<ul>
<li data-ng-repeat="items in shop | unique : 'cat' | orderBy: 'cat'">
<h2>{{items.cat}}</h2>
<ul>
<li ng-repeat="items in shop | filter:{cat: items.cat} | filter:query"
<h3>{{items.name}}</h3>
</li>
</ul>
</li>
</ul>
My Filter "unique" looks like so:
app.filter('unique', function() {
return function(collection, keyname) {
var output = [],
keys = [];
angular.forEach(collection, function(item) {
var key = item[keyname];
if(keys.indexOf(key) === -1) {
keys.push(key);
output.push(item);
}
});
return output;
};
});
JSON:
{
"businesses" : {
"-KQ1ggyrnYGYL1084Htz" : {
"name" : "business name",
"cat" : "food",
},
}
I assume that I could do something with ng-if and/or ng-hide/show but none of the combos I have done work.
You can use the ngIf directive or the ngShow/ngHide directives.
How you use them depends on your JSON.
Heres an example of the ngIf with some basic data:
(function() {
angular.module('MyApp', []);
})();
(function() {
angular.module('MyApp').controller('MyController', MyController);
MyController.$inject = ['$scope'];
function MyController($scope) {
$scope.shop = [{
name: "test 1",
cat: "cat 1"
}, {
name: "test 2",
cat: "cat 3"
}, {
name: "test 3",
cat: ""
}, {
name: "test 4",
cat: "cat 4"
}];
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="MyApp">
<div data-ng-controller="MyController">
<ul>
<li data-ng-repeat="items in shop | orderBy: 'cat'" ng-if="items.cat">
<h2>{{items.cat}}</h2>
<ul>
<li ng-repeat="items in shop | filter:{cat: items.cat}">
<h3>{{items.name}}</h3>
</li>
</ul>
</li>
</ul>
</div>
</div>

Sort a nested Array (2D Array) array from filter of angularjs

How I Sort a nested Array (2D Array) array from filter of angularjs. It's very Complicated for Me. anybody can help. appreciated for me. thanks...
I have a 2D Array. now how I sort it within ng-repeat.
Template File...
<ul>
<span ng-repeat="list in lists">
<li ng-repeat="list_ in list.list1 | orderBy:'name'">{{list_.name}}</li>
</span>
</ul>
JS file...
$scope.lists = [
{
no : 1,
list1 : [{
name : 'A'
},
{
name : 'M'
}]},
{
no : 2,
list1 : [{
name : 'B'
}]},
{
no : 5,
list1 : [{
name : 'Z'
}]},
{
no : 3,
list1 : [{
name : 'X'
},
{
name : 'T'
}]}
]
plunker here
It could achievable by flatten the array will all the inner object at the same level using custom filter
Markup
<body ng-app="myApp" ng-controller="myCon">
<ul>
<span ng-repeat="list in lists | flatten | orderBy:'+name'">
<li>{{list.name}}</li>
</span>
</ul>
</body>
Filter
app.filter('flatten', function(){
return function(array){
var flattenArray = [];
angular.forEach(array, function(value, index){
angular.forEach(value.list1, function(val, index){
flattenArray.push(val);
})
})
return flattenArray;
}
})
Plunkr Here
to answer your question of how to sort a nested Array array with an angularjs filter, you actually are already doing so. It isn't clear with your data, so I expanded it to make it show what is happening already:
http://plnkr.co/edit/8SjuLc?p=preview
js
var app = angular.module("myApp", []);
app.controller("myCon", myConFun);
myConFun.$inject = ['$scope'];
function myConFun($scope) {
$scope.lists = [{
no: 1,
list1: [{
name: 'Z'
}, {
name: 'X'
}, {
name: 'Y'
}, {
name: 'A'
}, {
name: 'M'
}, {
name: 'C'
}, {
name: 'B'
}]
}, {
no: 2,
list1: [{
name: 'B'
}]
}, {
no: 5,
list1: [{
name: 'Z'
}]
}, {
no: 3,
list1: [{
name: 'X'
}, {
name: 'T'
}]
}
]
}
html
<ul>
<span ng-repeat="list in lists">
<li ng-repeat="sublist in list.list1 | orderBy:'name'">
{{sublist.name}}
</li>
----------
</span>
</ul>
output:
You may need to expand your question further if this isn't the behavior you need

Filter Data in nested json

My angular controller is following -
how to filter nested data like first row of json-
<script>
var myApp = angular.module('myApp', ['angular.filter']);
function VersionFilterCtrl($scope) {
$scope.limit=6;
$scope.orders = [
{ id:1, customer:[{ name: 'John1', id: 10 },{ name: 'John2', id: 100 }] },
{ id:2, customer: { name: 'William', id: 20 } },
{ id:3, customer: { name: 'John', id: 10 } },
{ id:4, customer: { name: 'William', id: 20 } },
{ id:5, customer: { name: 'Clive', id: 30 } }
];
}
</script>
and my html
<div ng-app="myApp">
<div ng-controller="VersionFilterCtrl">
<input type='text' name='name' ng-model='search.customer.name'>
<input type='text' name='name' ng-model='search.customer.id'>
<li ng-repeat="order in orders| filterBy: ['customer.name']: search.customer.name| filterBy: ['customer.id']: search.customer.id">
{{order.id}}{{order.customer.name}}
</li>
</div>
</div>
JSFIDDLE EXAMPLE
You approached this correctly in how you set up your search models to match the structure of the data you are filtering, i.e. search.customer.name and search.customer.id.
All you need to do is to apply the search object as the filter:
<li ng-repeat="order in orders | filter: search">
{{order.id}} | id: {{order.customer.id}} name: {{order.customer.name}}
</li>
plunker
A few other issues:
There is no filterBy (unless you create your own)
Your first order record has an array of customers - was this intentional? This plunker handles that case

Angular ng-repeat for duplicates

I use Angular, this is my view:
<div class="col-sm-6" ng-repeat="contact in service.contacts">
<label class="control-label mb10">{{contact.textDescription | decodeURIComponent}}</label>
<select multiple="multiple" selectize>
<option>{{contact.value}}</option>
</select>
</div>
I have one problem and I can't figure out a way to solve it. For contact.textDescription, I need to put only unique values, so if that contact.textDescription is duplicate, don't create field twice, but add that contact.value to options of that same contact.textDescription which already exists.. So, something like this:
if(contact.textDescription is duplicate) {
contact.value.addTo(contact.textDescription which already exists)
}
Maybe some filter to apply or?
By the understanding of what you mentioned I think the filter mention in the following answer will help you to do what you want
Use this link to go to the question
You can use ng-options to group and display unique value.
You can use uniqFilter of angular-filter module.
Usage: collection | unique: 'property' or nested.property
Aliases: uniq
Example:
JS:
function MainController ($scope) {
$scope.orders = [
{ id:1, customer: { name: 'John', id: 10 } },
{ id:2, customer: { name: 'William', id: 20 } },
{ id:3, customer: { name: 'John', id: 10 } },
{ id:4, customer: { name: 'William', id: 20 } },
{ id:5, customer: { name: 'Clive', id: 30 } }
];
}
HTML:
<th>Customer list:</th>
<tr ng-repeat="order in orders | unique: 'customer.id'" >
<td> {{ order.customer.name }} , {{ order.customer.id }} </td>
</tr>
RESULT:
Customer list:
- John 10
- William 20
- Clive 30
Grouping your contacts by textDescription should resolve your problem. Try something like this:
html:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - GroupBy Filter</title>
<script src="angular-1.4.7.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app">
<div ng-controller="MainController">
<div ng-repeat="(key, contacts) in (service.contacts | groupBy: 'textDescription')">
<label class="control-label">{{key}}</label>
<select multiple="multiple" selectize>
<option ng-repeat="contact in contacts">{{contact.value}}</option>
</select>
</div>
</div>
</body>
script.js:
var app = angular.module("app", []);
app.controller("MainController", function ($scope) {
$scope.service = {};
$scope.service.contacts = [{
"textDescription": "td1",
"value": "1"
}, {
"textDescription": "td2",
"value": "2"
}, {
"textDescription": "td3",
"value": "3"
}, {
"textDescription": "td1",
"value": "4"
}, {
"textDescription": "td3",
"value": "5"
}, {
"textDescription": "td1",
"value": "6"
}];
});
app.filter('groupBy', function () {
var results={};
return function (data, key) {
if (!(data && key)) return;
var result;
if(!this.$id){
result={};
}else{
var scopeId = this.$id;
if(!results[scopeId]){
results[scopeId]={};
this.$on("$destroy", function() {
delete results[scopeId];
});
}
result = results[scopeId];
}
for(var groupKey in result)
result[groupKey].splice(0,result[groupKey].length);
for (var i=0; i<data.length; i++) {
if (!result[data[i][key]])
result[data[i][key]]=[];
result[data[i][key]].push(data[i]);
}
var keys = Object.keys(result);
for(var k=0; k<keys.length; k++){
if(result[keys[k]].length===0)
delete result[keys[k]];
}
return result;
};
});
Now you have all the contacts grouped by textDescription, so the field for it (<label>) is created only once and the values are added to <option> tags

Categories