How do I set an initial filter for my Json data in Angular.js?
I'm having a hard time (days searching and reading) setting an initial value for my data coming from a rails Json file.
My app is related to incident tickets and while I get all db records in data-ng-repeat, I cannot set the default view, eg. Only show unopened tickets at the start when you first load the page. I would also like the entire dataset to be filterable when I call ng-click and various conditions.
ticket_controllers.rb
var ticketControllers = angular.module('ticketControllers', []);
ticketControllers
.controller('ticketListController', ['$scope', 'Ticket',
function ($scope, Ticket) {
$scope.tickets_all = Ticket.query();
$scope.orderProp = 'opened_date';
$scope.getAllTickets = function (ticket) {
return $scope.tickets_all;
};
$scope.getClosedTickets = function (ticket) {
if (ticket.status === 'CL') {
return true;
}
return false;
};
$scope.getUnsolvedTickets = function (ticket) {
if (ticket.status === 'IP' || ticket.status === 'WF') {
return true;
}
return false;
};
$scope.getAbortedTickets = function (ticket) {
// console.log("Just called" + self.ticket);
if (ticket.status === 'AB') {
return true;
}
return false;
};
$scope.styleTicketStatus = function (status) {
switch (status){
case ("IP") : return "ui small circular teal label"; break;
case ("WF") : return "ui small circular purple label"; break;
case ("CL") : return "ui small circular black label"; break;
case ("AB") : return "ui small circular black label"; break;
default: break;
}
};
}]);
template
<table class="ui table raised segment">
<thead>
<tr>
<th></th>
<th class="text-center six column wide">Issue</th>
<th class="text-center">Category</th>
<th class="text-center">Requester</th>
<th class="text-center">Pending for</th>
<th class="text-center">Owner</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="ticket in getAllTickets() | filter : search | filter : statusOrder ">
<td class="text-center">
<div>
<span class="{{styleTicketStatus(ticket.status)}}">
{{ticket.status}}
</span>
</div>
</td>
<td>
<a href="/tickets/{{ticket.id}}" class="ticket_link">{{ticket.issue}} </a>
<br /><small>{{ticket.explanation}}</small>
</td>
<td class="text-center">{{ticket.ticket_category.category}}</td>
<td>{{ticket.user.lastname}}, {{ticket.user.firstname}}</td>
<td class="text-center">{{ticket.date_opened| date:'MM/dd h:mm'}}</td>
<td>{{ticket.owner.lastname}}, {{ticket.owner.firstname}}</td>
</tr>
</tbody>
</table>
sidebar (filters ..)
<div class="ui ">
<div class="ui input small fluid">
<input type="text" placeholder="Search in tickets..." class="" ng-model="search.issue" >
</div>
</div>
<div class="ui vertical fluid small menu ticket-sidebar">
<a class="active teal item" ng-click="statusOrder = getUnsolvedTickets">
My unsolved tickets
<div class="ui teal label">{{ (tickets_all | filter:getUnsolvedTickets ).length }}</div>
</a>
<a class="item" ng-click="statusOrder = getUnsolvedTickets">
All unsolved tickets
<div class="ui label">{{ (tickets_all | filter:getUnsolvedTickets ).length }}</div>
</a>
<a class="item" ng-click="statusOrder = getAbortedTickets">
Aborted tickets
<div class="ui label">{{ (tickets_all | filter:getAbortedTickets ).length }}</div>
</a>
<a class="item" ng-click="statusOrder = getClosedTickets">
Closed tickets
<div class="ui label">{{ (tickets_all | filter:getClosedTickets ).length }}</div>
</a>
<a class="item" ng-click="statusOrder = getAllTickets">
All tickets
<div class="ui label">{{tickets_all.length}}</div>
</a>
</div>
Can someone shed some light on my way?
source to share
The best approach is to handle the filtering inside your controller and be able to modify the list based on the filtered list.
You can access any of the filters programmatically with $filter
, for example:
//Get a reference to the 'filter' Filter
var filterFilter = $filter('filter');
//Execute the filter against a list
var filteredList = filterFilter(list, 'substring');
Using this approach gives you a lot of flexibility in your controller. You can set some options based on user input / action and then execute all filters at the same time, which is more efficient than using them in bindings.
You can see this in action below:
(function() {
function ticketCtrl($filter) {
var $this = this;
//Get a reference to the 'filter' Filter
var filter = $filter('filter');
//Set the initial filter to status === 'Unresolved'
changeStatusFilter('Unresolved');
//Changes the status filter and filters the list
// based on user input
function changeStatusFilter(status) {
//Set the new status filter for use in the UI
$this.statusFilter = status;
//If we are viewing all statuses, just copy the
// original list to the one being bound in the UI
if (status === 'All') {
$this.filteredTickets = angular.copy(allTickets);
return;
}
//Set the list being bound in the UI by running
// it through the 'filter' Filter using a custom
// predicate that matches on status exactly
$this.filteredTickets = filter(allTickets, function(ticket) {
return ticket.status === $this.statusFilter;
});
};
//Create a function that can be used from the UI
// to determine if a given status matches the
// currently selected filter
function isCurrentFilter(status) {
return $this.statusFilter === status;
};
//Because we are using the "Controller as" syntax
// the entire controller will be bound to the scope.
// Anything we want to be available to the UI needs
// to be exposed on the controller. We can do this
// by adding properties and methods to 'this' which
// is aliased here using the '$this' variable
$this.isCurrentFilter = isCurrentFilter;
$this.changeStatusFilter = changeStatusFilter;
}
//Set up our dependencies using the '$inject'
// notation.
ticketCtrl.$inject = ['$filter'];
angular.module('ticket-app', [])
.controller('ticketCtrl', ticketCtrl);
//Just some static data for demo purposes
var allTickets = [{
number: '1234',
name: 'Answer Question',
status: 'Resolved'
}, {
number: '3982',
name: 'Include Snippet',
status: 'Resolved'
}, {
number: '0283',
name: 'Get Upvotes',
status: 'Unresolved'
}, {
number: '0273',
name: 'Make Pretty',
status: 'Resolved'
}, {
number: '8902',
name: 'Mark Accepted',
status: 'Unresolved'
}, {
number: '1908',
name: 'Solve World Hunger',
status: 'Unresolved'
}, {
number: '7923',
name: 'Pick up dry cleaning',
status: 'Unresolved'
}];
}());
<script src="http://code.angularjs.org/1.3.0/angular.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" />
<!-- -->
<div class="container" ng-app="ticket-app" ng-controller="ticketCtrl as ctrl">
<div class="row">
<div class="col-sm-12">
<ul class="nav nav-tabs" role="tablist">
<li ng-class="{active:ctrl.isCurrentFilter('Unresolved')}">
<a ng-click="ctrl.changeStatusFilter('Unresolved')" href="">Unresolved</a>
</li>
<li ng-class="{active:ctrl.isCurrentFilter('Resolved')}">
<a ng-click="ctrl.changeStatusFilter('Resolved')" href="">Resolved</a>
</li>
<li ng-class="{active:ctrl.isCurrentFilter('All')}">
<a ng-click="ctrl.changeStatusFilter('All')" href="">All</a>
</li>
</ul>
<table class="table">
<thead>
<tr>
<th>Ticket #</th>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="ticket in ctrl.filteredTickets">
<td>{{ticket.number}}</td>
<td>{{ticket.name}}</td>
<td>
<span class="label" ng-class="{'label-success':ticket.status==='Resolved','label-danger':ticket.status==='Unresolved'}">{{ticket.status}}</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
source to share