ng-repeat orderBy with double digit number - angularjs

I have names such as:
Name - Page 9
Name - Page 2
Name - Page 6
Name - Page 15
Name - Page 1
Name - Page 12
Name - Page 14
Name - Page 13
Name - Page 10
Name - Page 11
Currently I am doing:
<div ng-repeat="data in results | orderBy:'-name'">
{{ data.name }}
</div>
But it doesn't order it with the numbers taken into consideration.
Does anyone know how I can make sure it is ordered according to the numbers?

<!DOCTYPE html>
<html>
<head>
<script src="angular.js"></script>
</head>
<body data-ng-app="app">
<div data-ng-controller="testC">
<div ng-repeat="data in results | orderBy:['name']">-{{data.name}}</div>
</div>
</body>
</html>
<script type="text/javascript">
var app = angular.module('app', []);
app.controller('testC', ['$scope', function($scope) {
$scope.results = [{'name':'Page 21'},
{'name':'Page 12'},
{'name':'Page 10'},
{'name':'Page 01'},
{'name':'Page 30'},
{'name':'Page 15'},
{'name':'Page 05'}];
}]);
</script>
it is working for me ,please try once .
https://jsfiddle.net/shivtumca12/nqbLLr4x/
and also
https://jsfiddle.net/shivtumca12/LxLu8v70/

It should work as expected. Check this plunker that I created.
Plunker Code
Edit: To handle double digits you can write a custom sort function like this:
$scope.myValueFunction = function(value) {
var numpart = value.name.replace( /^\D+/g, '');
return -(numpart-1000);
}
What this does is extract the number part and make it a sortable number. You can remove the preceding -ve sign to get ascending order.
Then in your html, you can call this function like this:
<tr ng-repeat="friend in friends | orderBy:myValueFunction">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>

Related

ng-repeat get length of array and bind last value of array

$scope.GetDetails={
Student:[
{"id":1,"Name":"Apple","Price":3500}
],
Student:[
{"id":2,"Name":"Samsung","Price":4000}
],
Student:[
{"id":3,"Name":"Nokia","Price":1500},
{"id":3,"Name":"Nokia","Price";7000}
]
}
Am binding data using ng-repeat
<div ng-repeat="As in GetDetails">
<div ng-repeat="A in As.Student">
<span>{{A.Name}}</span> - <span>{{A.Price}}</span>
</div>
</div>
Result is
Apple - 3500
Samsung - 4000
Nokia - 1500
Nokia - 7000
Here every thing Ok.But what i want mean , Nokia have two array ,so i have to get name from first array and price from 2nd array Like,
Nokia - 7000,
And Also i need the length of student array.
First, You should change your JSON to achieve your result.
Change JSON to below:
$scope.GetDetails=[
{Student:[{"id":1,"Name":"Apple","Price":3500}]},
{Student:[{"id":2,"Name":"Samsung","Price":4000}]},
{Student:[{"id":3,"Name":"Nokia","Price":1500},{"id":3,"Name":"Nokia","Price":7000}]}
]
Please run below code
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="As in GetDetails">
<div ng-repeat="A in As.Student" ng-if="$last">
<span>{{A.Name}}</span> - <span>{{A.Price}}</span>
</div>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.GetDetails=[
{Student:[{"id":1,"Name":"Apple","Price":3500}]},
{Student:[{"id":2,"Name":"Samsung","Price":4000}]},
{Student:[{"id":3,"Name":"Nokia","Price":1500},{"id":3,"Name":"Nokia","Price":7000}]}
]
});
</script>
</body>
</html>
I used ng-if="$last" to take the last value from array
Here is a working DEMO
If you want this only for Name: Nokia, then do it like;
<div ng-repeat="A in As.Student">
<span ng-if="A.Name!=='Nokia'">{{A.Name}}-{{A.Price}}</span>
<span ng-if="A.Name==='Nokia' && $last">{{A.Name}}-{{A.Price}}</span>
</div>
and it you want only last element from every array :
then:
<div ng-repeat="A in As.Student" ng-if="$last">
<span>{{A.Name}}</span> - <span>{{A.Price}}</span>
</div>

Switch between displayed data

I've started looking at AngularJS a few hours ago so I'm settling into how things work. As part of a basic example, I'm trying to figure out how I switch between displayed data in a table.
At the moment, I've got the following as my basic app;
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
</head>
<body>
<div ng-app="applicationMain" ng-controller="controllers.app.main">
<table>
<tr ng-repeat="item in items">
<button>Toggle</button>
<td>{{item.name}}<td>
</tr>
</table>
</div>
</body>
<script>
var controllers = {
app : {
main : function($scope){
var s = $scope;
s.items = [
{
name : "Pizza",
price : 100
},
{
name : "Burger",
price : 45
},
{
name : "Kebab",
price : 85
}
];
}
}
}
var app = angular.module("applicationMain", []);
app.controller('controllers.app.main', controllers.app.main);
</script>
</html>
Fairly simple. Scoped array of objects with name and price fields, where the name of each is displayed in a table using ng-repeat
What I'd like to do is when I click the Toggle button, it switches between displaying the data of item.name to displaying data of item.price.
Is this something that can be done within the angular expression of the <TD> tags, or would a function be the way to go?
If I was using regular old JS for example, I might do something like this;
var activeField = item.name;
if (activeField == item.name){
activeField = item.price
} else {
activeField = item.name
}
However, I tried something similar by creating a 'switchField' function in my controller, but Angular reports that 'item is not defined' (essentially a scoping issue) even when defining it at $scope.item.price and $scope.item.name respectively.
You can do something like this, using ngClick, ngShow and ngHide:
<table>
<tr ng-repeat="item in items">
<button ng-click="toggleIt()">Toggle</button>
<td ng-show="toggle">{{item.name}}<td>
<td ng-hide="toggle">{{item.price}}<td>
</tr>
</table>
And add this to the controller:
s.toggle = true;
s.toggleIt = function() {
s.toggle = !s.toggle;
}

Filter first value of array inside ng-repeat in angularjs

How can i filter josn first element of a row inside ng-repeat using angularjs.
i am stuck with this.
My sample code is::
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<div>
<div ng-repeat="x in num| orderBy:'n'">
<b>{{x.n}}</b>
<div ng-repeat="y in amt | orderBy:'v'">
<div ng-if="x.n==y.n">
<div>{{y.v}}</div>
</div>
</div >
<br />
</div>
<script>
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.num= [
{n:'3'},
{n:'1'},
{n:'2'},
];
$scope.amt= [
{n:'1',v:'23'},
{n:'1',v:'24'},
{n:'1',v:'45'},
{n:'2',v:'56'},
{n:'2',v:'67'},
{n:'2',v:'45'},
{n:'3',v:'23'},
{n:'3',v:'67'},
{n:'3',v:'19'},
];
});
</script>
</body>
</html>
Result is
1
23
24
45
2
45
56
67
3
19
23
67
I am result only. first value.
like:
1
23
2
45
3
19
Please help...
You should create custom filter function:
$scope.myFilter = function (x) {
return function (y) {
if (x.n==y.n) {
return true;
} else {
return false;
}
}
};
Use it in inner ng-repeat:
<div ng-repeat="y in amt | orderBy:'v' | filter:myFilter(x) | limitTo:1">
<div>{{y.v}}</div>
</div >
Also, to get top 1 result add standard limitTo filter (limitTo:1), wich first argument sets max return count.
(...)
< /tr>
< /thead>
< tbody>
< tr ng-repeat="object in objects | SOME_FILTER">
(...)
{{object.get("element")}}
{{(object.get("element2")).innerElement}}
(...)
< /tr>
< /tbody>
< /table>
(...)
The 3 dots means that there was some code cut out. "element2" is the one with a JSON inside. "innerElement" is the key. it worked for me, hope would be useful to someone

Filter an array by two different criteria

I have the below code which uses a controller to grab the contents of a JSON file and then display the first 5 results. The code also includes a filter to allow users to search.
The filter looks for results in both name and code (see below JSON example), which is great. However, I'd like for the filter to do more; code is unique, and if a match to code is found it should be displayed at the top of the list, with the remaining four results listed by name underneath.
For example, if the user was to search for swi, currently the five results that are listed are -
Brunswick (BRW)
Chiswick (CHK)
Derby Road (Ipswich) (DBR)
Giggleswick (GIG)
Hutton Cranswick (HUT)
What I would like is -
Swindon (SWI)
Brunswick (BRW)
Chiswick (CHK)
Derby Road (Ipswich) (DBR)
Giggleswick (GIG)
Is this possible using AngularJS, or would I be looking at using some more complex logic to get my desired results?
JSON example
[
{
"name": "Abbey Wood",
"code": "ABW"
},
{
"name": "Aber",
"code": "ABE"
},
{
"name": "Abercynon",
"code": "ACY"
}
]
My code
<!DOCTYPE html>
<html lang="en-GB" data-ng-app="tigerSelector">
<head>
<meta charset="UTF-8">
<title>Tiger | Staff CIS Selector</title>
<!-- Mobile stuff -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<!-- Angular JS -->
<script src="angular/angular.js"></script>
<script type="text/javascript">
var app = angular.module('tigerSelector', []);
app.controller('stationsCtrl', function($scope, $http){
$http.get('stations.json').then(function(res){
$scope.stations = res.data;
});
});
</script>
</head>
<body>
<div data-ng-controller="stationsCtrl">
<p>Filtering input:</p>
<p><input type="text" data-ng-model="search"></p>
<ul>
<li data-ng-repeat="station in stations | filter:search | orderBy:'name' | limitTo:5">
{{ station.name }} ({{ (station.code | uppercase) }})
</li>
</ul>
</div>
</body>
</html>
You can create custom filter, and iterate over your collection, and passing your search ngModel to the filter.
Filter
(function(){
function filter(){
return function (input, search) {
var out = [];
//Map over the input
[].map.call(input || [], function(elm){
//Compare code value to search model
elm.code.toLowerCase() === search
//Push elm at the beginning of the array
? out.unshift(elm)
//Otherwise, add element to the end of the array
: out.push(elm);
});
//Return our filtered array
return out;
};
}
angular
.module('app')
.filter('myFilter', filter);
})();
Then you can call your filter into your template. You can combine multiple filter.
HTML
<p><input type="text" data-ng-model="search"></p>
<ul>
<li data-ng-repeat="station in stations | myFilter:search | filter:search | limitTo:5">
{{ station.name }} ({{ (station.code | uppercase) }})
</li>
</ul>

ng-repeat orderBy suddenly stopped sorting

The data being shown in the ng-repeat is acquired from a firebase db and as such is loaded asynchronously
this is the HTML:
<tr ng-animate="{enter: 'animate-enter', leave: 'animate-leave'}" ng-repeat="player in players|orderBy:'-Level'" class="neutral">
<td>{{$index+1}}</td>
<td>{{player.PlayerName}}</td>
<td>{{player.Wins}}</td>
<td>{{player.Losses}}</td>
<td>{{player.Level}}</td>
</tr>
And this is my controller:
app.controller 'RankController', ($scope, angularFire) ->
$scope.players;
ref = new Firebase("https://steamduck.firebaseio.com/players")
angularFire(ref, $scope, 'players')
What am I doing wrong? why is the list not being ordered by Level?
edit: Turns out this works perfectly if I use the model made by lukpaw. As such the problem must be in the data I receive which looks like this :
I think that your sorting is OK.
I did simple example and it works in your way. Maybe something which did not you placed is wrong in your code (first check JavaScript console).
HTML:
<!doctype html>
<html ng-app="App">
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<div ng-controller="Ctrl">
<table border="1">
<tr ng-animate="{enter: 'animate-enter', leave: 'animate-leave'}" ng-repeat="player in players | orderBy:'-Level'">
<td>{{$index+1}}</td>
<td>{{player.PlayerName}}</td>
<td>{{player.Wins}}</td>
<td>{{player.Losses}}</td>
<td>{{player.Level}}</td>
</tr>
</table>
</div>
</body>
</html>
JavaScript:
angular.module('App', []);
function Ctrl($scope) {
$scope.players =
[{PlayerName:'John', Wins: 12, Losses:10, Level: 2},
{PlayerName:'Mary', Wins:7, Losses:19, Level: 1},
{PlayerName:'Mike', Wins:5, Losses:21, Level: 1},
{PlayerName:'Adam', Wins:9, Losses:35, Level: 3},
{PlayerName:'Julie', Wins:10, Losses:29, Level: 2}]
}
Plunker example
It would appear that the orderBy filter only knows how to sort an array. As such this would never work with JSON objects being used as the model.
I ended up implementing my own filter :
app.filter "orderObjectBy", ->
(input, attribute) ->
return input unless angular.isObject(input)
array = []
for key of input
array.push input[key ]
array.sort (a, b) ->
a = parseInt(a[attribute])
b = parseInt(b[attribute])
b - a
ng-repeat="player in players | orderObjectBy:'Level'"
How about ng-repeat="player in players|orderBy:Level:reverse"?
Inspired by #RonnieTroj answer, this filter reuses built-in orderBy filter and can handle both arrays and objects of any comparable type, not just integers:
app.filter 'orderCollectionBy', ['orderByFilter', (orderByFilter) ->
(input, attribute, reverse) ->
return unless angular.isObject input
if not angular.isArray input
input = (item for key, item of input)
orderByFilter input, attribute, reverse
]

Resources