AngularJS multiple filters - angularjs

I want to filter my list's items using multiple filters.
This is how I fill my items list (Using Django):
<script type="text/javascript">
ngApp.controller('FilterInputCtrl', function ($scope, $rootScope) {
$scope.items1 = [];
{% for cross in crosses%}
$scope.items.push
({
id:{{ cross.id }},
name: '{{ cross.name }}',
comments: '{{ cross.comments }}',
aliases: '{{ cross.print_lines_aliases }}',
});
{% endfor %}
});
</script>
The one filter code is like this:
<li ng-repeat="cross in items | filter:myFilter">
which filters on all the item's fields (id, name, ... etc).
I want to filter the same way but using multiple filters that filter on all fields too. So the user may remeber segments from the name so he enters many segments from the name and then he maye remeber a segment from the comments and so on.
I found this way:
<li ng-repeat="cross in items | filter:{ name: filter1, lines: filter2, comments: filter3 }">
Which works fine, but each filter now is specific for one criterion.
The problem is that I don't know how will the user think when searching; maybe he will search for many segements of the comments!
I am looking for a way to apply many filters and each one filters according to every field without specifying a single field to each one.
Something looks like this maybe:
<li ng-repeat="cross in items | filter:{filter1, filter2, filter3}">

<li ng-repeat="cross in filteredItems = (items | filter:filter1 | filter:filter2 | filter:filter3)">
If you notice, I have created a new scope variable there called filteredItems. This makes it easy to check if there are any items left after filtering. You may wish to display a message such as "No items found" if !filteredItems.length.
E.g.
<div ng-hide="filteredItems.length" class="row">
<div class="col-xs-10 col-sm-11 col-md-11">No items found</div>
</div>

var app =angular.module('app', []);
app.controller('mainController', function($scope) {
// Data object
$scope.servers = [
{name:'ServerA', runlevel:'PAV', mode:'author', env:'intranet' },
{name:'Server7', runlevel:'PAV', mode:'publish', env:'intranet'},
{name:'Server2', runlevel:'PAV', mode:'publish', env:'intranet'},
{name:'ServerB', runlevel:'PAV', mode:'publish', env:'internet'},
{name:'ServerC', runlevel:'PAV', mode:'publish', env:'internet'},
{name:'Server1', runlevel:'UAT', mode:'author', env:'intranet'},
{name:'Server3', runlevel:'UAT', mode:'publish', env:'intranet'},
{name:'Server4', runlevel:'UAT', mode:'publish', env:'internet'},
{name:'ServerD', runlevel:'STA', mode:'author', env:'intranet'},
{name:'ServerE', runlevel:'STA', mode:'publish', env:'intranet'}
];
// Filter defaults
$scope.Filter = new Object();
$scope.Filter.runlevel = {'PAV':'PAV',
'UAT':'UAT',
'ST':'ST'
};
$scope.Filter.mode = {'author':'author',
'publish':'publish'
};
$scope.Filter.env = {'intranet':'intranet',
'internet':'internet'
};
// Default order
$scope.OrderFilter = 'runlevel';
});
// Global search filter
app.filter('searchFilter',function($filter) {
return function(items,searchfilter) {
var isSearchFilterEmpty = true;
angular.forEach(searchfilter, function(searchstring) {
if(searchstring !=null && searchstring !=""){
isSearchFilterEmpty= false;
}
});
if(!isSearchFilterEmpty){
var result = [];
angular.forEach(items, function(item) {
var isFound = false;
angular.forEach(item, function(term,key) {
if(term != null && !isFound){
term = term.toString();
term = term.toLowerCase();
angular.forEach(searchfilter, function(searchstring) {
searchstring = searchstring.toLowerCase();
if(searchstring !="" && term.indexOf(searchstring) !=-1 && !isFound){
result.push(item);
isFound = true;
}
});
}
});
});
return result;
}else{
return items;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="mainController">
<h2>Runlevel</h2>
<label>PAV</label>
<input type="checkbox" ng-model="Filter.runlevel.PAV" ng-true-value="PAV" ng-false-value="!PAV" />
<label>UAT</label>
<input type="checkbox" ng-model="Filter.runlevel.UAT" ng-true-value="UAT" ng-false-value="!UAT" />
<label>ST</label>
<input type="checkbox" ng-model="Filter.runlevel.ST" ng-true-value="ST" ng-false-value="!ST"/>
<hr />
<h2>Runmode</h2>
<label>Author</label>
<input type="checkbox" ng-model="Filter.mode.author" ng-true-value="author" ng-false-value="!author" />
<label>Publish</label>
<input type="checkbox" ng-model="Filter.mode.publish" ng-true-value="publish" ng-false-value="!publish" />
<hr />
<h2>Environment</h2>
<label>Intranet</label>
<input type="checkbox" ng-model="Filter.env.intranet" ng-true-value="intranet" ng-false-value="!intranet" />
<label>Internet</label>
<input type="checkbox" ng-model="Filter.env.internet" ng-true-value="internet" ng-false-value="!internet" />
<hr />
<h2>Server list</h2>
<table width="100%" cellpadding="5">
<tr>
<th ng-click="OrderFilter='name'">Name</th>
<th ng-click="OrderFilter='runlevel'">Runlevel</th>
<th ng-click="OrderFilter='mode'">Runmode</th>
<th ng-click="OrderFilter='env'">Environment</th>
</tr>
<tr ng-repeat="server in servers | searchFilter:Filter.runlevel | searchFilter:Filter.mode | searchFilter:Filter.env | orderBy:OrderFilter">
<td>{{server.name}}</td>
<td>{{server.runlevel}}</td>
<td>{{server.mode}}</td>
<td>{{server.env}}</td>
</tr>
</table>
</div>
</div>

Related

filtering month in date angularjs

I 've successed to filter a date with angularjs. but I want to filter the month only. i want if I typed 01 only titanic appears. here is my sample data.
view
<input type="text" ng-model="search" />
<tr ng-repeat="n in eventlist | filter:search">
<td>{{n.name}}</td>
<td>{{n.date | date:"dd MMMM yyyy"}}</td>
</tr>
controller
$scope.eventlist = [
{name:"Titanic", date:"2016-01-24"},
{name:"Civil War", date:"2016-07-01"}
];
you should use custome filter for this. try like this.
var app = angular.module('main', []);
app.controller('DemoCtrl', function ($scope,$filter) {
$scope.eventlist =
[
{name:"Titanic", date:"2016-01-24"},
{name:"Civil War", date:"2016-02-15"}
];
$scope.myFilter = function(month,search){
return function(event) {
return event.date.split('-')[1] == $scope.search ?true:false;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="DemoCtrl" ng-app="main">
<input type="text" ng-model="search" />
<div ng-repeat="n in eventlist | filter:myFilter()" >
<span>{{n.name}}</span>
<span>{{n.date}}</span>
</div>
</div>

how get the list of selected items in angular.js

Here I am using angular.js to show a list of people
<div class="recipient" ng-repeat="person in people">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
$scope.people = [{id:1}, {id:2}, {id:3}, {id:4}];
The looks is like below
What I want to do is I can select multiple items and by click a OK button, I can get a list of selected items. so If I select id 1 and id 2, then I want to get return a list of [{id:1},{id:2}]
How could I implement it in angular.js
Well I guess that if you're looping through a collection of people using a ng-repeat, you could add the ng-click directive on each item to toggle a property of you're object, let's say selected.
Then on the click on your OK button, you can filter all the people that have the selected property set to true.
Here's the code snippet of the implementation :
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
<button ng-click="result()">OK</button>
function demo($scope) {
$scope.ui = {};
$scope.people = [{
name: 'Janis',
selected: false
}, {
name: 'Danyl',
selected: false
}, {
name: 'tymeJV',
selected: false
}];
$scope.selectPeople = function(people) {
people.selected = !people.selected;
};
$scope.result = function() {
$scope.ui.result = [];
angular.forEach($scope.people, function(value) {
if (value.selected) {
$scope.ui.result.push(value);
}
});
};
}
.recipient {
cursor: pointer;
}
.select {
color:green;
}
.recipient:hover {
background-color:blue;
}
<script src="https://code.angularjs.org/1.2.25/angular.js"></script>
<div ng-app ng-controller="demo">
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)" ng-class="{ select: person.selected }">
<div class="name">{{ person.name }}</div>
</div>
<button ng-click="result()">OK</button>
Result :
<ul>
<li ng-repeat="item in ui.result">{{ item.name }}</li>
</ul>
</div>
If you only want to show checked or unchecked you could just apply a filter, but you would need to toggle the filter value from undefined to true if you didn't wan't to get stuck not being able to show all again.
HTML:
<button ng-click="filterChecked()">Filter checked: {{ checked }}</button>
<div class="recipient" ng-repeat="person in people | filter:checked">
<input type='checkbox' ng-model="person.isChecked" />
<img ng-src="{{person.img}}" />{{ person.name }}
<div class="email">{{ person.email }}</div>
</div>
Controller:
// Apply a filter that shows either checked or all
$scope.filterChecked = function () {
// if set to true or false it will show checked or not checked
// you would need a reset filter button or something to get all again
$scope.checked = ($scope.checked) ? undefined : true;
}
If you want to get all that have been checked and submit as form data you could simply loop through the array:
Controller:
// Get a list of who is checked or not
$scope.getChecked = function () {
var peopleChkd = [];
for (var i = 0, l = $scope.people.length; i < l; i++) {
if ($scope.people[i].isChecked) {
peopleChkd.push(angular.copy($scope.people[i]));
// Remove the 'isChecked' so we don't have any DB conflicts
delete peopleChkd[i].isChecked;
}
}
// Do whatever with those checked
// while leaving the initial array alone
console.log('peopleChkd', peopleChkd);
};
Check out my fiddle here
Notice that person.isChecked is only added in the HTML.

Issue with Angular JS

I am a UI developer and I am completely new to Angular, however, I understand jQuery. I have joined a new company and they use Angular JS with JAVA. I have been assigned a task over which I am banging head for the past few days. I've come under the scanner now.
Basically I have a table in .html page to which data is coming (Sorry, I am told that I would need atleast 10 reputation to post a screen shot). Now I want to other column in that table.
I have tried adding that column in columns_panel.js but still it is not coming in the grid by default.
I understand that my question is not clear over here, but trust me, even my Team lead is also not willing to disclose any thing.
Can any JS guru's be help to me?
<div columns-panel columns="columns" show-panel="showColumnsPanel"></div>
<table class="responsive">
<thead>
<tr>
<th>
</th>
<th class="isFlagged">
<div class="flag"></div>
</th>
<th ng-repeat="column in columns" ng-click="sortBy(column)" class="{{ column }}">
<a class="th-inner">
{{ column | translate }}
<span ng-show="isSortColumn(column)"
ng-class="{'sort-icon-desc': !isSortAscending(),
'sort-icon-asc': isSortAscending()}">
</span>
</a>
</th>
<!--<th class="toggle-columns-header">-->
<!--<a class="th-inner" ng-click="showColumnsPanel = !showColumnsPanel">+</a>-->
<!--</th>-->
</tr>
</thead>
<tbody>
<tr ng-repeat="dispute in disputes.currentPage"
ng-class="isSelected(dispute) ? '{{ dispute | disputeTrClass }} checked-dispute' : '{{ dispute | disputeTrClass }}'"
ng-click="goToDisputeDetails(dispute)">
<td ng-class="isNegative(dispute) ? 'select-dispute alert-corner' : 'select-dispute'" ng-click="$event.stopPropagation()">
<input id="select-dispute-{{ dispute.id }}" type="checkbox" ng-click="toggleSelectedDispute(dispute)" ng-checked="isSelected(dispute)" ng-disabled="!dispute.isFlaggable" ng-hide="!dispute.isFlaggable" />
<label for="select-dispute-{{ dispute.id }}" ng-hide="!dispute.isFlaggable"></label>
</td>
<td class="isFlagged" ng-click="toggleFlag(dispute, $event)">
<div ng-show="dispute.isFlaggable" class="flag {{ dispute.isFlagged ? 'flagged' : 'unflagged' }}"></div>
</td>
<td ng-repeat="column in columns" class="{{ column }}">
<div data-ng-switch data-on="column">
<div data-ng-switch-when="reason">
{{ dispute[column] }}
<span class="reason-code" ng-if="dispute.reason !== 'N/A'">{{ dispute.reasonCode }}</span>
</div>
<div data-ng-switch-when="status">
{{ dispute[column]=="Urgent Response Required"?"Response Required":dispute[column] }}
</div>
<div data-ng-switch-when="amount">
<div ng-if="isNegative(dispute)" class="negative">
-<span class="currency">$</span>{{ dispute[column] * -1 | number:2 }}
</div>
<div ng-if="isPositive(dispute)">
<span class="currency">$</span>{{ dispute[column] | number:2 }}
</div>
</div>
<div data-ng-switch-when="dateReceived">
{{ dispute[column] | translatedDate }}
</div>
<div data-ng-switch-when="respondBy">
{{ dispute[column] | translatedDate }}
</div>
<div data-ng-switch-when="respondedOn">
{{ dispute[column] | translatedDate }}
</div>
<div data-ng-switch-default>
{{ dispute[column] }}
</div>
</div>
</td>
<!--<td class="{{ columns[columns.length - 1] }}"></td>-->
</tr>
</tbody>
</table>
<!-- No Disputes To Display -->
<div disputes-table-empty></div>
<!-- Error Message -->
<div disputes-table-error></div>
<style type="text/css">
.status {
padding-left: 27px !important;
}
</style>
This is the Model
DisputeModule.value('Dispute', function (attributes) {
this.id = attributes.id;
this.amount = attributes.amount;
this.cancelDate = attributes.cancelDate;
this.cancellationNumber = attributes.cancellationNumber;
this.cancelZone = attributes.cancelZone;
this.cardDeposit = attributes.cardDeposit;
this.cardMemberName = attributes.cardMemberName;
this.cardNumber = attributes.cardNumber;
this.chargeAmount = attributes.chargeAmount;
this.chargeDate = attributes.chargeDate;
this.creditReceived = attributes.creditReceived;
this.dateReceived = attributes.dateReceived;
this.disputeNumber = attributes.disputeNumber;
this.description = attributes.description;
this.isFlaggable = attributes.isFlaggable;
this.isFlagged = attributes.isFlagged;
this.locationID = attributes.locationID;
this.merchandiseReturned = attributes.merchandiseReturned;
this.merchandiseType = attributes.merchandiseType;
this.merchantAccount = attributes.merchantAccount;
this.modeOfReturn = attributes.modeOfReturn;
this.originalCardNbr = attributes.originalCardNbr;
this.payeeLocationId = attributes.payeeLocationId;
this.payeeSENbr = attributes.payeeSENbr;
this.reason = attributes.reason;
this.reasonCode = attributes.reasonCode;
this.referenceNumber = attributes.referenceNumber;
this.reservationCanceled = attributes.reservationCanceled;
this.reservationCanceledDate = attributes.reservationCanceledDate;
this.stage = attributes.stage;
this.status = attributes.status;
});
This is the columns_panel.js
DisputeModule.directive('columnsPanel', function (BASE_URL) {
var defaultColumns = [
'disputeNumber',
'status',
'dateReceived',
'respondBy',
'respondedOn',
'type',
'reason',
'cardNumber',
'originalCardNbr',
'transactionDate',
'referenceNumber',
'resolution',
'merchantAccount',
'locationID',
'payeeSENbr',
'payeeLocationId',
'chargeAmount',
'amount'
];
var availableColumns = [
'disputeNumber',
'status',
'dateReceived',
'respondBy',
'respondedOn',
'type',
'reason',
'cardNumber',
'originalCardNbr',
'transactionDate',
'referenceNumber',
'resolution',
'merchantAccount',
'locationID',
'payeeSENbr',
'payeeLocationId',
'chargeAmount',
'amount'
];
var columns = defaultColumns.slice();
return {
templateUrl: BASE_URL + '/resources/views/columns_panel.html',
scope: {
columns: '=',
showPanel: '='
},
controller: function ($scope) {
function addColumn(column) {
var tmpColumns = $scope.columns.slice();
tmpColumns.push(column);
tmpColumns.sort(function (a, b) {
return $scope.availableColumns.indexOf(a) - $scope.availableColumns.indexOf(b);
});
updateColumns(tmpColumns);
}
$scope.columns = columns;
$scope.availableColumns = availableColumns;
$scope.isSelected = function (column) {
return $scope.columns.indexOf(column) > -1;
};
$scope.toggleColumn = function (column) {
var columnIndex = $scope.columns.indexOf(column);
if (columnIndex === -1) {
addColumn(column);
} else {
$scope.columns.splice(columnIndex, 1);
}
};
$scope.reset = function () {
updateColumns(defaultColumns.slice());
};
$scope.close = function () {
$scope.showPanel = false;
};
function updateColumns(newColumns) {
$scope.columns = columns = newColumns;
}
}
};
});
I want to add "chargeAmount" to appear in the grid/table
you must have another columns somewhere, this columns
<div columns-panel columns="columns" show-panel="showColumnsPanel"></div>
try to add to your directive datas (the columns).
they are called here
scope: {
columns: '=',
showPanel: '='
},
and gave to the directive scope here
$scope.columns = columns;
so in your controller try to see what you have in columns

angularJS: Filter JSON Data w.r.t Date Range

I am completely new to AngularJS. Here is my HTML code
<div ng-controller="DateRangeCtrl">
<div class="container">
<div class="form-horizontal">
<input type="text" datepicker-popup="MM-dd-yyyy" ng-model="dt1" is-open="opened1" max="maxFromDate" ng-change="setMinToDate()"/>
<button class="btn btn-sm" ng-click="open1($event)"><span class="glyphicon glyphicon-calendar"></span></button>
</div>
<div class="form-horizontal">
<input type="text" datepicker-popup="MM-dd-yyyy" ng-model="dt2" is-open="opened2" min="minToDate" max="maxToDate" ng-change="filterDateAdded()"/>
<button class="btn btn-sm" ng-click="open2($event)"><span class="glyphicon glyphicon-calendar"></span></button>
</div>
<p><strong>Selected From Date: </strong> {{dt1 | date:'mediumDate'}}</p>
<p><strong>Selected To Date: </strong> {{dt2 | date:'mediumDate'}}</p>
</div>
<hr />
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Date Added</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items | orderBy:mySortFunction ">
<td>{{item.ID}}</td>
<td>{{ parseDate(item.dateAdded) | date:'longDate'}}</td>
</tr>
</tbody>
</table>
</div>
The following is my angular code:
testApp.config(function (datepickerConfig, datepickerPopupConfig) {
datepickerConfig.showWeeks = false;
datepickerPopupConfig.showButtonBar = false;
});
testApp.controller('DateRangeCtrl', function($scope) {
$scope.items = [
{ID: "1", dateAdded: "01-04-2013"},
{ID: "2", dateAdded: "12-01-2013"},
{ID: "3", dateAdded: "12-31-2013"},
{ID: "4", dateAdded: "01-12-2014"},
{ID: "5", dateAdded: "03-04-2014"}
];
$scope.parseDate = function(input){
var parts = input.split('-');
var newParts = new Date(parts[2], parts[0]-1, parts[1]); // Note: months are 0-based
return newParts;
}
$scope.open1 = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened1 = true;
};
$scope.maxFromDate = new Date();
$scope.maxToDate = new Date();
$scope.setMinToDate = function (){
$scope.dt2 = null;
$scope.minToDate = $scope.dt1;
};
$scope.open2 = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened2 = true;
};
});
How can i filter rows based on selected dates? For e.g. if i select "01/01/2014" in the "From" datePicker then i should be able to see all the rows whose "Date Added" column has value more than "January 1, 2014". The output will be rows with ID: 4 and 5.
It should behave the literal equivalent way when the "To" datePicker is selected
Please help me out. i'm stuck!
Update:
HTML
<tr ng-repeat="item in items | filter:dateFilter ">
JS
$scope.dateFilter = function (item) {
return (item.dateAdded < $scope.dt2);
};
Am i doing anything wrong? It still doesn't work....
By some hit n trial method, i eventually got it right. The problem was the "item.dateAdded" string had to be converted to Date object. Solution is adding the following piece of code in the js file:
$scope.filterDateAdded = function (){
if($scope.dt1 != null)
{
$scope.dateFilter = function (item) {
return ($scope.parseDate(item.dateAdded) >= $scope.dt1 && $scope.parseDate(item.dateAdded) <= $scope.dt2);
};
}
};
Cheers!
Change your code like this
<input type="text" datepicker-popup="MM-dd-yyyy" ng-model="dt2" is-open="opened2" min="minToDate" max="maxToDate" ng-model="search" ng-change="filterDateAdded()"/>
<tr ng-repeat="item in items | filter:dateFilter">
$scope.filterDateAdded=function()
{
$scope.dateFilter = function () {
var result=[];
for(var i in $scope.item)
{ if($scope.item[i].dateAdded >$scope.search)
{
result.push($scope.item[i]);
}
}
return result;
};
}

Angular filter using OR instead of AND logic

I'm having some checkboxes and on check, table filter values. But if I select active and draft it doesn't show anything because it's implementing AND logic, I need filters that is using OR logic.
<div class="clearfix">
<input data-ng-model="active" data-ng-true-value="active" class="pull-left" type="checkbox" id="active"/>
<label class="pull-left" for="active">Active</label>
</div>
<div class="clearfix">
<input data-ng-model="draft" data-ng-true-value="draft" class="pull-left" type="checkbox" id="draft"/>
label class="pull-left" for="draft">Draft</label>
</div>
<table class="table">
<tr ng-repeat="campaign in dashboard.campaigns | filter:all | filter:active | filter:draft">
<td>{{campaign.name}}</td>
<td>{{campaign.startDate}}</td>
<td>{{campaign.endDate}}</td>
<td>{{campaign.status}}</td>
<td>{{campaign.tasks}}</td>
</tr>
Edit:
here is the solution
app.filter('byStatus', [function () {
return function (campaigns, active, draft) {
var tempCampaigns = [];
angular.forEach(campaigns, function (campaign) {
if(campaign.status == active || campaign.status == draft ){
tempCampaigns.push(campaign);
}
});
return tempCampaigns;
};
}]);
<tr ng-repeat="campaign in dashboard.campaigns | byStatus:active:draft">
thx all ;)
You just need to implement custom filter like this:
angular.module('App.filters', []).filter('activeOrDraft', [function () {
return function (campaigns) {
if (!angular.isUndefined(campaigns)) {
var tempCampaigns = [];
angular.forEach(campaigns, function (campaign) {
if (campaign.active || campaign.draft) {
tempCampaigns.push(campaign);
}
});
return tempCampaigns;
} else {
return campaigns;
}
};
}]);
and use it instead of filter:active | filter:draft like this:
| activeOrDraft
Not sure about meaning of all in your code, so add it if needed.

Resources