Angular order dropdown select list - angularjs

How I can order the list in select dropdown using Angular ?
This is the angular controller:
var app = angular.module("app", []);
app.controller('Ctrl', function($scope, $filter, $http) {
$scope.options= [
{
"id": 823,
"value": "81"
},
{
"id": 824,
"value": "77"
},
{
"id": 825,
"value": "152"
},
];
});
And html:
<h4>Angular-xeditable Editable row (Bootstrap 3)</h4>
<div ng-app="app" ng-controller="Ctrl">
<select ng-model="test" ng-options="v.id as v.value for v in options | orderBy: value"></select>
</div>
Now the order is: 81, 77, 152
And I want: 77,81,152
How I can do it ?
Jsfiddle to test
Thanks

Your values are strings so they won't be naturally ordered unless you convert them to integers.
You may convert them by creating your own filter or by defining a simple sorting function on your $scope:
Fiddle
<select
ng-model="test"
ng-options="v.id as v.value for v in options | orderBy: naturalOrder"
></select>
$scope.naturalOrder = function(item){
return parseInt(item.value, 10);
};

You need to place single quotes around the name of the field in your orderBy. The first argument to orderBy is a sort expression string.
in options | orderBy:'value'
You can extend this by adding a + or - before the field name to indicate initial sort direction. You can also provide a boolean value after the sort expression to enable toggling of the sort direction.
<div ng-init="desc=true">
...
in options | orderBy:'+value':desc

Related

Set selected option in angular js based on ordinal position of item

I am loading a select control in angular js from an array of json objects.
I want to set the selected property if the ordinal position of an item in the collection matches some value (such as 3 for example), eg,
<option ng-repeat="query in ReportQueries" selected="query.ordinal==3"
value="query.ReportQueryID">{{query.QueryName}}</option>
There is no property "ordinal" on my object, I am hoping there is some index or counter angular generates and exposes when iterating through a collection.
Does anyone know if this is possible? Thanks
Thanks
Here is an Example which may help you: Updated
angular.module('myApp', [])
.controller('myCtrl', function($scope) {
$scope.test = 3;
$scope.ReportQueries = [{
ReportQueryID: 1,
QueryName: 'Amy'
}, {
ReportQueryID: 2,
QueryName: 'Ben'
}, {
ReportQueryID: 3,
QueryName: 'Betty'
}, {
ReportQueryID: 4,
QueryName: 'Hannah'
}, {
ReportQueryID: 5,
QueryName: 'John'
}]
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<select ng-model="test">
<option ng-repeat="query in ReportQueries" ng-selected="test==$index">{{query.QueryName}}</option>
</select>
<h1>Selected Index is: {{test}}</h1>
</div>

How to order strings by length with orderBy filter?

I have this code which work as expected providing me all the items starting with the letters I type in :
<input name="search-bar" id="search-bar" type="text" ng-model="search"
typeahead="res.label for res in result | filter:$viewValue:startsWith |
limitTo:20">
But I want the suggestions to be ordered by the length of the label, so I tried two things without any luck :
1st try
<input name="search-bar" id="search-bar" type="text" ng-model="search"
typeahead="res.label for res in result | filter:$viewValue:startsWith |
limitTo:20 | orderBy:'res.label'">
2nd try
<input name="search-bar" id="search-bar" type="text" ng-model="search"
typeahead="res.label for res in result | filter:$viewValue:startsWith |
limitTo:20 | orderBy:'res.label.length'">
EDIT (controller code) :
var url = "/data/list.json";
var items = $http.get(url).then(function(response){
$scope.result = response.data; //result is filled with a static json containing all the data
$scope.loading = false;
});
JSON sample (from /data/list.json) :
[{"code":64,"label":"ALPAGA (64)"},{"code":44,"label":"ALPA (44)"}]
What am I missing ?
You can use a custom orderBy routine like in this runnable fiddle demo or just try orderBy:'label.length' which directly interacts with the iterated object attribute. Both approaches should work for you in a fine way.
View
<div ng-controller="MyCtrl">
<div ng-repeat="item in data | orderBy:orderByLength">
{{ item.label }}
</div>
</div>
AngularJS application
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.data = [{
"code": 64,
"label": "ALPAGA (64)"
}, {
"code": 44,
"label": "ALPA (44)"
}, {
"code": 24,
"label": "ALPA (12344)"
}, {
"code": 48,
"label": "ALPA (42324df)"
}];
$scope.orderByLength = function (item) {
return item.label.length
}
});

Is there a way to escape dot notation in AngularJS groupBy expression?

I am using this AngularJS filter: https://github.com/a8m/angular-filter#groupby
I have a piece of data (JSON) involving key names containing dots, which seems to be mistaken with nested properties.
Is there a way to prevent the filter from parsing the dot notation or an alternate way to specify the name of the field used for grouping ?
Note: I can't change the way data are build from the server.
My code looks like this :
<div ng-repeat="(key, values) in items | groupBy: 'category_id.name'" >
<div class="item-row">
{{key}}
</div>
<div class="badge-row" ng-repeat="item in values">
{{item.name}}
</div>
</div>
And here is the JSON data I get from the server :
[
{
"id": "1",
"name": "test",
"category_id.name": "Main"
},
{
"id": "2",
"name": "foo",
"category_id.name": "Other category"
},
{
"id": "3",
"name": "bar",
"category_id.name": "Test"
}
]
When running this code, at the moment, I am getting 'undefined' as key value.
Angular Filter uses $parse, so that you can order by fields in nested objects
I have a workaround for this problem. If it helps.
Template:
(key, values) in items | groupBy: rawProperty('category_id.name')
Controller:
$scope.rawProperty = function(key) {
return function(item) {
return item[key];
};
};
JS Bin Demo
Hope it helps.

How to sort on input text in Angular?

I am new to Angular. I have an input text box where I am going to enter sorting criteria like "rating" and "date". I have a controller defined with data.
comments: [{
rating:5,
date:"2012-10-16T17:57:28.556094Z"
},
{
rating:4,
date:"2014-09-05T17:57:28.556094Z"
}]
How can I define filters which will do the sorting based on input?
Working Plnkr
In this example, when you type rating or date in input text field, it will sort the data based on this value. I have called the method on key press. If you want to sort after clicking on sort button, add a button and call he sorting method on ng-click.
var myApp = angular.module('myApp',[]);
myApp.controller('MyController',function($scope,$filter){
$scope.test = 'This is a test!';
$scope.comments = [
{
rating:5,
date:"2012-10-16T17:57:28.556094Z"
},
{
rating:4,
date:"2014-09-05T17:57:28.556094Z"
},
{
rating:7,
date:"2010-09-05T17:57:28.556094Z"
}];
$scope.comments2 = $scope.comments;
$scope.$watch('sortItem', function(val)
{
if(val==='rating' || val==='date'){
$scope.comments = $filter('orderBy')($scope.comments2,val);
}
else{
return;
}
});
});
Hope that solve your problem.
You can use a collections library like underscorejs, and it will be like,
Bind your input box value to a variable as,
<select ng-model=inputVal></select>
Inside your controller function,
$scope.arr = _.sortBy($scope.originalArray, function(o) {
return o[$scope.inputVal];
})
Is this process not working?
<div ng-app ng-controller="myCtrl">
<input type="text" ng-model="sortOption" />
<ul>
<li ng-repeat="comment in comments | orderBy: sortOption">
rate: {{comment.rating}}
</li>
</ul>
AngularJS
$scope.sortOption = "rating";
$scope.comments = [
{
rating:4,
date:"2015-10-16T17:57:28.556094Z"
},
{
rating:5,
date:"2014-09-05T17:57:28.556094Z"
}
]
In your controller add this:
this.sortOption = ''
Call the sortOption above on your input text as follow:
ng-model="sortOption"
Finally modify your ng-repeat as follow:
ng-repeat="comment in YourControllerName.comments|orderBy: sortOption"
In a nutshell :if you type :date then it sorts by date. If you type author then it sorts by author, if you type rating then it sorts by rating.
All you need to do is to apply ng-model to your input to create a binding no need for ng-click. With two way data binding once the input field is touched the filter will be applied so:
<input type="text" ng-model="orderKey" name="orderField">
then using the repeat directive
ng-repeat = "comment in comments | orderBy:orderKey"
Pay attention to spacing between orderBy and the (:) NO SPACE

Disabling nesting filter in AngularJS

There is the following code:
tr ng-repeat="order in orders | filter: { restaurant: { id: currentRestaurant.id } } | orderBy:'-id'"
This code works good and filter orders by restaurant.id correctly. But I need to disable this filter in some case in order to show all orders. My controller code:
$scope.setCurrentRestaurant = (restaurant) ->
$scope.currentRestaurant = restaurant
I don't know how I can disable filtering programmatically or using filter directive. Thanks in advance.
If the filter parameter is undefined then it does not filter. If the filter parameter is the filtering expression, then it filters based on that.
So, you could introduce a filter expression like so:
"filter: (enableFilter || undefined) && {restaurant:{id:currentRestaurant.id}}"
plunker
I think that Angular doesn't contain native features for that.
But you can create custom solution for this case.
For example, you can broadcast event, when you want to disable filter. This event can be broadcasted from anywhere (service, directive, controller). For simplicity, here I've broadcasted it from controller.
Also I've created filterByRestaurant in the controller.
View:
<div ng-controller="MyCtrl">
<div ng-repeat="order in orders | filter:filterByRestaurant">
{{order.name}}
</div>
<button ng-if="enableFilter" ng-click="disableOrEnableFilter()">Disable filter</button>
<button ng-if="!enableFilter" ng-click="disableOrEnableFilter()">Enable filter</button>
</div>
Controller:
function MyCtrl($scope, $rootScope) {
$scope.enableFilter = true;
$scope.currentRestaurant = {id: 2, name: "Rest2"};
$scope.orders = [
{id:1, restId: 1, name: "order from Rest1"},
{id:2, restId: 2, name: "order from Rest2"},
{id:3, restId: 3, name: "order from Rest3"}
];
$scope.filterByRestaurant = function(order) {
return $scope.currentRestaurant.id == order.restId || !$scope.enableFilter;
};
$scope.$on('filter:disable', function() {
$scope.enableFilter = !$scope.enableFilter;
});
$scope.disableOrEnableFilter = function(){
$rootScope.$broadcast("filter:disable");
};
}
This is working JSFiddle with example.
Hope it will help.

Resources