I'm trying to filter a list that contains a timestamp by typing a range of dates
for example:
JSFIDDLE
html
<div ng-app="tst">
<div ng-controller="MyController">
<table>
<tr>
<td>From:
<input ng-model="query.date1" type="text" placeholder="" />
</td>
<td>To:
<input ng-model="query.date2" type="text" placeholder="" />
</td>
</tr>
<tr ng-repeat="order in orders |filter:query">
<td>{{order.date1 * 1000 | date:'dd-MM-yyyy'}}</td>
<td>{{order.date2 * 1000 | date:'dd-MM-yyyy'}}</td>
</tr>
</table>
</div>
</div>
javascript
var nameSpace = angular.module('tst',[]);
nameSpace.controller('MyController', function MyController($scope) {
$scope.orders = [
{
"date1":"1306487800",
"date2":"1406587800"
},
{
"date1":"1196487800",
"date2":"1406597800"
}]
});
i want to be able to fill the "From" field with the value : 27-05-2010
and the "To" field the value of : 29-07-2015
and get only the records that are in this range.
(the first record in the example).
Thanks allot Avi
The ng-repeat values can be filtered according to the ng-model in AngularJS by using the value of the input field as an expression in a filter. We can set the ng-model directive on an input field to filter ng-repeat values.
You can consider using transclusion inside a custom directive, to achieve the behavior you are looking for without using ng-repeat.
Definition and UsageThe ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.
Note: The $index variable is used to get the Index of the Row created by ng-repeat directive. Each row of the HTML Table consists of a Button which has been assigned ng-click directive. The $index variable is passed as parameter to the GetRowIndex function.
You can create a custom filter to achieve this aim.
JSFIDDLE
html
<input ng-model="dateFrom" type="text"/>
<input ng-model="dateTo" type="text"/>
<tr ng-repeat="order in orders | myfilter:dateFrom:dateTo">
<td>{{order.date1 * 1000 | date:'dd-MM-yyyy'}}</td>
<td>{{order.date2 * 1000 | date:'dd-MM-yyyy'}}</td>
</tr>
javascript
function parseDate(input) {
var parts = input.split('-');
return new Date(parts[2], parts[1]-1, parts[0]);
}
nameSpace.filter("myfilter", function() {
return function(items, from, to) {
var df = parseDate(from);
var dt = parseDate(to);
var result = [];
for (var i=0; i<items.length; i++){
var tf = new Date(items[i].date1 * 1000),
tt = new Date(items[i].date2 * 1000);
if (tf > df && tt < dt) {
result.push(items[i]);
}
}
return result;
};
});
also, i changed the timestamp data type from string to numbres.
$scope.orders = [
{
"date1": 1306487800,
"date2": 1406587800
},
{
"date1": 1196487800,
"date2": 1406597800
}]
I have created a filter with momentJS to make things easier:
.filter('dateRange', function() {
return function(items, startDate, endDate) {
var retArray = [];
if (!startDate && !endDate) {
return items;
}
angular.forEach(items, function(obj) {
var receivedDate = obj.date;
if (moment(receivedDate).isAfter(startDate) && moment(receivedDate).isBefore(endDate)) {
retArray.push(obj);
}
});
return retArray;
}
})
For time manipulation I strongly recommend libraries such as momentJS; with momentJS and modern browsers this can be achieved in a very declarative way:
.filter('dateRange', function() {
return function(items, startDate, endDate) {
//an undefined startDate is converted to the beginning of time
startDate = startDate || 0;
const granularity = null // can be 'days', ... see momentJS doc
//you need support for array.prototype.filter and arrow functions; i.e. IE sucks/needs a polyfill
return items.filter(item => moment(item).isBetween(startDate, endDate, granularity, '[]'));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With