Simple pagination with angularjs - angularjs

I'd like to implement pagination with AngularJS but I have some problems.
I don't know how to update the $scope.agreements object when clicking on a new page...
var app = angular.module("GestiawebApp", []);
app.controller("AgreementsController", function($scope, $http) {
var nbPages, limit;
$http.get('/api/agreement').success(function(data, status, headers, config) {
limit = data.limit;
nbPages = Math.ceil(data.agreements.length/data.limit);
$scope.agreements = data.agreements.slice(0, limit);
});
$scope.getPages = function() {
var pages = [];
for (var i = 1; i <= nbPages; i++) {
pages.push(i);
}
return pages;
};
$scope.goToPage = function(page){
// simple test to change the agreements, but it seem's not working
$scope.agreements = $scope.agreements.slice(page*limit, (page*limit)+limit);
};
});
<!-- Loop -->
<tr ng-repeat="agreement in agreements | filter:search">
<td>{{agreement.number}}</td>
<td>{{agreement.reference}}</td>
<td>
{{agreement.billbook.capital}} €
</td>
</tr>
<!-- End loop -->
<!-- Paginaiton -->
<ul>
<li ng-repeat="i in getPages() track by $index" ng-click="goToPage($index+1)">{{$index+1}</li>
</ul>
<!-- End pagination -->

You should store all agreements data in a variable to use for paginating
$scope.allAgreements = [];
$http.get('/api/agreement').success(function(data, status, headers, config) {
limit = data.limit;
nbPages = Math.ceil(data.agreements.length/data.limit);
$scope.allAgreements = data.agreements; //new change
$scope.agreements = $scope.allAgreements.slice(0, limit);
});
$scope.goToPage = function(page){
// simple test to change the agreements, but it seem's not working
$scope.agreements = $scope.allAgreements.slice(page*limit, (page*limit)+limit);
};

Related

Angular - Trying to access value outside of $http get success and use it for a filter value

I'm building a silly little Football app. On the first page, I am trying to load the country's top division standings and the coming week's fixtures.
I retrieve the data, using a RESTful Web Service and so is done asynchronously. The table is fine, but not the fixtures.
There is an array of fixture objects, within them, there's a 'matchday' and 'status' property. If you look at the 'this.getFixtures' function, look at the success code block. What I am trying to do is only display the fixtures for a certain match day. If there is one game left to be played on a certain matchday, then I only want that fixture displayed. If not, display next matchday's fixtures.
The 'status' property typically has a value of 'SCHEDULED' or 'FINISHED'. In the success code block I am saying:
Loop through all fixtures retrieved.
If this fixture is scheduled, that means, we're on the matchday for this fixture.
In which case, break loop.
I am then trying to use that value outside the get method, but I keep getting undefined. Is there any way to access that value outside the success block?
I'll use the $scope.matchDay function as the filter.This will help me to only display scheduled fixtures in that matchday with ng-repeat.
Anyway, sorry for the long winded post, but here's the code:
HTML:
<div class="grid-x">
<div class="medium-8 medium-offset-2 cell">
<div id="premier-league-banner">
<div class="banner-shade">
<div class="grid-x">
<div class="medium-5 cell">
<table>
<tr ng-repeat="team in premierLeagueTable.standing | limitTo: 6">
<th>{{ $index + 1 }}</th>
<td><img class="prem-thumbnail" src="{{ team.crestURI }}" /></td>
<th>{{ team.teamName }}</th>
<th>{{ team.playedGames }}</th>
<th>{{ team.goalDifference }}</th>
<th>{{ team.points }}</th>
</tr>
</table>
</div>
<div class="medium-2 cell">
<img src="images/prem-logo.png" />
</div>
<div class="medium-5 cell">
<table>
<tr ng-repeat="fixture in premierLeagueFixtures.fixtures | filter:{matchday: 10}">
<th>{{fixture.homeTeamName}}</th>
<td>vs</td>
<th>{{fixture.awayTeamName}}</th>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
Angular JS
// MODULE
var quickEleven = angular.module('quickEleven', ['ngRoute', 'ngResource']);
// ROUTES
quickEleven.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.htm',
controller: 'homeController'
})
});
// CONTROLLERS
quickEleven.controller('homeController', ['$scope', '$resource', '$log', 'footballData', function($scope, $resource, $log, footballData) {
function getMonday(date) {
var day = date.getDay() || 7;
if( day !== 1 )
date.setHours(-24 * (day - 1));
return date;
}
function convertDate(date) {
var yyyy = date.getFullYear().toString();
var mm = (date.getMonth()+1).toString();
var dd = date.getDate().toString();
var mmChars = mm.split('');
var ddChars = dd.split('');
return yyyy + '-' + (mmChars[1]?mm:"0"+mmChars[0]) + '-' + (ddChars[1]?dd:"0"+ddChars[0]);
}
var thisMonday = getMonday(new Date);
var nextMonday = getMonday(new Date);
nextMonday.setDate(nextMonday.getDate() + 7);
$log.info("Boom! " + convertDate(thisMonday));
$log.info("For! " + convertDate(nextMonday));
$scope.premierLeagueTable = footballData.getLeagueTable("http://api.football-data.org/v1/competitions/:competitionId/leagueTable", 445);
//http://api.football-data.org/v1/competitions/:competitionId/fixtures?timeFrameStart=2018-03-01&timeFrameEnd=2018-03-05
//"http://api.football-data.org/v1/competitions/:competitionId/fixtures/?matchday=9"
$scope.premierLeagueFixtures = footballData.getFixtures("http://api.football-data.org/v1/competitions/:competitionId/fixtures?timeFrameStart=" + convertDate(thisMonday) + "&timeFrameEnd=" + convertDate(nextMonday), 445);
$log.info($scope.premierLeagueFixtures);
$log.info($scope.premierLeagueTable);
$scope.matchdayValue = 9;
$scope.matchDay = function() {
return footballData.getMatchday();
};
}]);
quickEleven.service('footballData', ['$resource', '$log', function($resource, $log) {
//Referring to the latest matchday with the status as 'SCHEDULED'
var self = this;
var test;
self.latestScheduledMatchday = 0;
self.getMatchday = function() {
$log.info("This is: " + test);
return self.latestScheduledMatchday;
}
this.getLeagueTable = function (footballUrl, compId) {
this.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
this.fussball = data;
}, function(err) {
$log.error(err);
});
return this.footballAPI;
};
this.getFixtures = function (footballUrl, compId) {
// var self;
this.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
// self = data.fixtures;
self.latestScheduledMatchday = data.fixtures[0].matchday
for (var i = 0; i < data.fixtures.length; i++) {
var fixture = data.fixtures[i];
if (fixture.status == 'SCHEDULED') {
test = fixture.matchday;
break;
}
}
$log.info("Dollar signs... " + test);
}, function(err) {
$log.error(err);
});
return this.footballAPI;
};
}]);
I see 2 issues so far. One on the note of undefined values is your service might not be getting implemented correctly. AFAIK you should be returning the service in the "function($resource, $log) {" function.
Here's how I'd change it (note I've not tested this)
quickEleven.service('footballData', ['$resource', '$log', function($resource, $log) {
//Referring to the latest matchday with the status as 'SCHEDULED'
var wrappedService = {};
var test;
var latestScheduledMatchday = 0;
var getMatchday = function() {
$log.info("This is: " + test);
return latestScheduledMatchday;
}
wrappedService.getLeagueTable = function (footballUrl, compId) {
wrappedService.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
wrappedService.fussball = data;
}, function(err) {
$log.error(err);
});
return wrappedService.footballAPI;
};
wrappedService.getFixtures = function (footballUrl, compId) {
wrappedService.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
latestScheduledMatchday = data.fixtures[0].matchday
for (var i = 0; i < data.fixtures.length; i++) {
var fixture = data.fixtures[i];
if (fixture.status == 'SCHEDULED') {
test = fixture.matchday;
break;
}
}
$log.info("Dollar signs... " + test);
}, function(err) {
$log.error(err);
});
return wrappedService.footballAPI;
};
return wrappedService;
}]);
So instead of the function returning no service, you have your service wrapped and returned as I believe you were intending. I also removed references to "self" since your intention there (internal service variables) is more eloquently handled with var scoping in the function.
Second issue that you will see once your service is working.
$scope.premierLeagueTable = footballData.getLeagueTable("http://api.football-data.org/v1/competitions/:competitionId/leagueTable", 445);
This line does not return the request data, but returns the request object. In fact by the time $scope.premierLeagueTable is set, the request hasn't even completed yet. What you do get is access to a promise that you can put a callback function in. See the angular resource documentation for more info, specifically the third example in the user-resource section where you see .$promise https://docs.angularjs.org/api/ngResource/service/$resource#user-resource.
Whatever functionality you want to apply the data return to should live inside that .$promise.then(...) callback. I'm not entirely sure if the promise in there receives the response data, or your callback return. You'll have to read further or experiment to find that out.

How to update an AngularJS table cell value from database without refresh

I have an application which displays a table (xeditable) by retrieving data from a mySQL database.
The database table which displays the content constantly changes in the background and I am trying to figure out how I can reflect those changes in the UI without refreshing the page or the entire table each time a change was made in the database.
Basically, I would like to "push" the changes to the view and a change has been detected in the database.
I understand that is not available with PHP/MySQL so I guess there must be a way around it by using either a 3rd party library or even a mid tier nodeJS...
I read on google's firebase (with ReactJS) how this can be achieved OTB and thought it may be possible to do without rewriting my entire app.
Any thoughts?
snippets of my current codebase:
app.js
var app = angular.module('myApp', ['ui.bootstrap','countTo','xeditable']);
app.filter('startFrom', function() {
return function(input, start) {
if(input) {
start = +start; //parse to int
return input.slice(start);
}
return [];
}
});
app.filter('abs', function () {
return function(val) {
return Math.abs(val);
}
});
app.run(function(editableOptions) {
editableOptions.theme = 'bs3'; // bootstrap3 theme. Can be also 'bs2', 'default'
});
app.config(['$compileProvider', function($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|http?|file|data):/);
}]);
app.controller('customersCrtl', function ($scope, $http, $timeout, $interval, $window) {
var init = function loadItems(){
$scope.$emit('LOAD');
$scope.progressBar = { progress : 0 };
$http.get('ajax/getItems.php').success(function(data){
$scope.list = data;
$scope.updateID = data.updateID;
$scope.currentPage = 1; //current page
$scope.entryLimit = 50; //max no of items to display in a page
$scope.filteredItems = $scope.list.length; //Initially for no filter
$scope.totalItems = $scope.list.length;
$scope.priceInfo = {
min: 0,
max: 100000
}
$scope.$emit('UNLOAD');
var array = $scope.list;
var flags = [], output = [], l = array.length, i;
for(i=0; i<l; i++) {
if( flags[array[i].category]) continue;
flags[array[i].category] = true;
output.push(array[i].category);
}
var array_manufact = $scope.list;
var flags = [], output_manufact = [], l = array_manufact.length, i;
for( i=0; i<l; i++) {
if( flags[array_manufact[i].manufacturer]) continue;
flags[array_manufact[i].manufacturer] = true;
output_manufact.push(array_manufact[i].manufacturer);
}
$scope.cats = output;
$scope.manufact = output_manufact;
//console.log($scope.cats);
});
(function progress(){
if($scope.progressBar.progress < 100){
$timeout(function(){
$scope.progressBar.progress += 1;
progress();
},5);
}
})();
index.html:
<html>
<tbody>
<tr ng-repeat="data in filtered = (list | filter:search | filter:{category:by_cat} | filter:{notes:by_notes} | filter:{Locked:by_search_locked} | filter:{external_link:by_external_link} | filter:{name:by_name} | filter:{cat2:by_cat2} | filter:{errorStatus:search`enter code here`_status} | filter:{error_status:search_status_opt} | orderBy : predicate :reverse) | startFrom:(currentPage-1)*entryLimit | limitTo:entryLimit" ng-class="{'success' : data.error_status=='--example1--', 'warning' : data.place_1_name!='my_stock', 'danger' : data.error_status == 'not loaded'}">
<td ng-class='{red : data.Locked==1}'><center>{{data.ID}}</center></td>
<td ng-class='{red : data.Locked==1}'><center>{{data.name}}</center></td>
<td ng-class='{red : data.Locked==1}'>
<center>
cat: {{data.category}}
<br/>
cat2: {{data.category2}}
</center></td>
<td ng-class='{red : data.Locked==1}'><center>{{data.price}}</center></td>
<td ng-class='{red : data.Locked==1}'><center>
<div ng-if="data.notes.length > 0">
<div ng-repeat="i in data.notes">
<b><font color="red">{{i}}</font></b>
</div>
</div>
<div ng-if="data.notes.length==0">
---
</div>
</center>
</td>
<td ng-class='{red : data.Locked==1}'>
<center>
<div ng-if="data.minPrice !=''">
<a href="#" editable-text="data.minPrice" onbeforesave="updateMinPrice(data.productID,$data)">
<font class='green'>{{data.minPrice}}</font>
</a>
<span ng-if="data.minPrice_last_changed!='---'">
<br/>
<br/>
LastChangedON: <font dir="ltr">{{data.minPrice_last_changed}}</font>
</span>
</div>
<div ng-if="data.minPrice == '' ">
<div editable-text="data.minPrice" onbeforesave="updateMinPrice(data.productID,$data)">
<font class='orange'>click to add</font>
</div>
</div>
</center></td>
</html>
Use the $interval1 service to poll your endpoint
app.controller('MainCtrl', function($scope, $http, $interval) {
$interval(function(){
$http.get('/api/metrics').then(function(res){
$scope.data = res.data;
});
},5000);
});
Here is a plunker simulating polling an endpoint with $interval
https://docs.angularjs.org/api/ng/service/$interval

if number of results returned > X then hide element angularjs

I would like to detect the amount of results returned in an ng-repeat loop and then if it is more than a certain number, execute code eg. hide an HTML tag. So if p in pics is more than X then hide something. Not sure how to go about it:
Here is a snippet of my code:
HTML
<li ng-repeat="p in pics">
<img ng-src="{{p.images.thumbnail.url}}" />
<p>{{p.comments.data|getFirstCommentFrom:'alx_lloyd'}}</p>
</li>
JS
(function(){
//Place your own Instagram client_id below. Go to https://instagram.com/developer/clients/manage/ and register your app to get a client ID
var client_id = ''; //redacted
//To get your user ID go to http://jelled.com/instagram/lookup-user-id and enter your Instagram user name to get your user ID
var user_id = ''; //redacted
var app = angular.module('instafeed', ['ngAnimate']);
app.filter('getFirstCommentFrom',function() {
return function(arr, user) {
for(var i=0;i<arr.length;i++) {
if(arr[i].from.username==user)
return arr[i].text;
}
return '';
}
})
app.factory("InstagramAPI", ['$http', function($http) {
return {
fetchPhotos: function(callback){
var endpoint = "https://api.instagram.com/v1/users/self/media/liked/";
endpoint += "?access_token=foobar";
endpoint += "&callback=JSON_CALLBACK";
/* var endpoint = "https://api.instagram.com/v1/users/" + user_id + "/media/recent/?";
endpoint += "?count=99";
endpoint += "&client_id=" + client_id;
endpoint += "&callback=JSON_CALLBACK";
*/
$http.jsonp(endpoint).success(function(response){
callback(response.data);
});
}
}
}]);
app.controller('ShowImages', function($scope, InstagramAPI){
$scope.layout = 'grid';
$scope.data = {};
$scope.pics = [];
InstagramAPI.fetchPhotos(function(data){
$scope.pics = data;
console.log(data)
});
});
})();
You can use ng-hide since your pics are just in an array and check the length of the array, e.g:
<h2 ng-hide="pics.length > 5">HIDE ME</h2>
(function() {
//Place your own Instagram client_id below. Go to https://instagram.com/developer/clients/manage/ and register your app to get a client ID
var client_id = '83aaab0bddea42adb694b689ad169fb1';
//To get your user ID go to http://jelled.com/instagram/lookup-user-id and enter your Instagram user name to get your user ID
var user_id = '179735937';
var app = angular.module('instafeed', ['ngAnimate']);
app.filter('getFirstCommentFrom', function() {
return function(arr, user) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].from.username == user)
return arr[i].text;
}
return '';
}
})
app.factory("InstagramAPI", ['$http',
function($http) {
return {
fetchPhotos: function(callback) {
var endpoint = "https://api.instagram.com/v1/users/self/media/liked/";
endpoint += "?access_token=179735937.83aaab0.e44fe9abccb5415290bfc0765edd45ad";
endpoint += "&callback=JSON_CALLBACK";
$http.jsonp(endpoint).success(function(response) {
callback(response.data);
});
}
}
}
]);
app.controller('ShowImages', function($scope, InstagramAPI) {
$scope.layout = 'grid';
$scope.data = {};
$scope.pics = [];
InstagramAPI.fetchPhotos(function(data) {
$scope.pics = data;
console.log(data)
});
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.js"></script>
<div ng-app='instafeed' ng-controller='ShowImages'>
<li ng-repeat="p in pics">
<a href="{{p.link}}" target="_blank">
<img ng-src="{{p.images.thumbnail.url}}" />
</a>
<p>{{p.comments.data|getFirstCommentFrom:'alx_lloyd'}}</p>
</li>
<h2 ng-hide="pics.length > 5">HIDE ME</h2>
</div>
If you want mean is something like "show only the first four results" then you can do this by using $index from the ng-repeat.
For instance the following will show items with 0 <= $index <= 3.
<li ng-repeat="p in pics" ng-if="$index < 4">
You can reference $index anywhere inside the repeat - not just on the repeat itself:
<li ng-repeat="p in pics">
<img ng-src="{{p.images.thumbnail.url}}" />
<p ng-if="$index<4">{{p.comments.data|getFirstCommentFrom:'alx_lloyd'}}</p>
</li>
Alternatively if you want to hide the whole lot then you should be able to take the length from the array:
<div id="container" ng-if="pics.length <= 4">
<li ng-repeat="p in pics">
...
</li>
</div>
For any of these you can choose between ng-if and ng-hide. I would tend to prefer ng-if, as it causes the render to be ignored completely. ng-hide will render all the markup, and then just set to display:none;, which is more likely to be useful where the condition can change due to the user's input to the page (for example).
As #DTing points out, you can also use a filter on the repeat itself if you want to apply the filter at that level:
<li ng-repeat="p in pics | limitTo: 4">

Angularjs ui bootstrap - Don't know how to cycle through table data with Pagination

I currently have a page that has clickable data. When clicked, a modal comes up that has a table built with customer data received from a service. I have included Angularjs ui boostrap plugin and have implemented the pagination directive. I have the pagination working in the sense that the links are able to switch back and forth as well as the previous and next buttons. What I do not know how to do is cycle through the table data displaying the amount specified in the controller. Code is below:
Drilldown Directive:
var drilldownDirective = function () {
return {
restrict: 'E',
scope: {
tableData: '='
},
controller: function ($rootScope, $scope, DashboardFactory) {
var tableData = $scope.tableData;
var dashboardreportid = tableData.dashboardreportid;
var companyid = tableData.companyid;
var companybrandid = tableData.companybrandid;
var startdate = tableData.startdate;
var enddate = tableData.enddate;
var clientdb = tableData.clientdb;
var calltype = tableData.calltype;
var secondarycallval = tableData.secondarycallval;
var onSuccess = function (response) {
var d, t, dt, dtobj, obj;
var dtData = [];
$scope.repdata = [];
$scope.titles = [];
for (d in response.repdata) {
var dtArray = [];
obj = response.repdata[d];
$scope.repdata.push(obj);
//Create data packages for dataTables
for (dt in obj.data) {
dtobj = obj.data[dt];
dtArray.push(dtobj);
};
//Push data package to dtData array for injecting in dataTable
dtData.push(dtArray);
//Dynamically save field name for table headers
if (obj.ID == 0) {
var tlt = obj.data;
for (t in tlt) {
$scope.titles.push(t);
};
$scope.titles.sort();
};
};
//Pagination controls
$scope.totalItems = $scope.repdata.length;
$scope.currentPage = 1;
$scope.maxSize = 5;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
};
$scope.pageChanged = function() {
console.log('Page changed to: ' + $scope.currentPage);
};
$scope.bigTotalItems = 175;
$scope.bigCurrentPage = 1;
};
var onError = function (response) {
console.log("error");
console.log(data);
};
DashboardFactory.getDashboardReportData(dashboardreportid, companyid, companybrandid, startdate, enddate, clientdb, calltype, secondarycallval).then(onSuccess, onError);
},
templateUrl: "dashboard/drilldownTable.html",
}
}
(directive template) drilldownTable.html
<input type='text' data-ng-model='searchbox' placeholder='search rows'></input>
<div class="table-responsive">
<table id="drilldownTable" class="table table-bordered table-condensed">
<thead>
<th data-ng-repeat="title in titles">{{title}}</th>
</thead>
<tbody>
<!-- <tr data-ng-repeat='rd in repdata | filter:searchbox | limitTo:50'> -->
<tr data-ng-repeat='rd in repdata | filter:searchbox | limitTo:bigTotalItems'>
<td data-ng-repeat='val in rd.data track by $index'>{{val}}</td>
</tr>
</tbody>
</table>
</div>
<pagination total-items="totalItems" data-ng-model="currentPage" data-ng-change="pageChanged()"></pagination>
<pre>Page: {{currentPage}} / {{maxSize}}</pre>
All help is appreciated. Thanks.

AngularJS filtering causes circular dependency error when using pagination

This is how I load the data
// Loads entire list of Metriclibs.
function HomeCtrl($scope, $http, $location) {
$scope.data = [];
$scope.pageSize = 100;
$scope.currentPage = 0;
$scope.lastPage = 0;
// This is async
$http.get('index.cfm/json/metriclib')
.success(function(data) {
$scope.data = data;
$scope.lastPage = Math.floor($scope.data.length/$scope.pageSize);
})
.error(function(data) {
console.log("Data load error");
})
;
$scope.go = function ( path ) {
$location.path( path );
};
$scope.numberOfPages=function(){
return $scope.lastPage;
}
}
This is how I show the data without pagination (this works)
<tr ng-repeat="datum in data | filter:search | limitTo:pageSize" class="odd">
This is me thing to set the starting point
<tr ng-repeat="datum in data | startFrom:0 | limitTo:pageSize" class="odd">
When I do the second one I get:
[19:58:24.355] "Error: Circular dependency:
getService#http://xxxxxxxx/toolbox_hacking/assets/angular.js:2855
#http://xxxxxxxx/toolbox_hacking/assets/angular.js:9604
filter#http://xxxxxxxx/toolbox_hacking/assets/angular.js:6157
_filterChain#http://xxxxxxxx/toolbox_hacking/assets/angular.js:6148
statements#http://xxxxxxxx/toolbox_hacking/assets/angular.js:6124
parser#http://xxxxxxxx/toolbox_hacking/assets/angular.js:6057
#http://xxxxxxxx/toolbox_hacking/assets/angular.js:6623
Scope.prototype.$eval#http://xxxxxxxx/toolbox_hacking/assets/angular.js:8057
ngRepeatWatch#http://xxxxxxxx/toolbox_hacking/assets/angular.js:13658
Scope.prototype.$digest#http://xxxxxxxx/toolbox_hacking/assets/angular.js:7935
Scope.prototype.$apply#http://xxxxxxxx/toolbox_hacking/assets/angular.js:8143
done#http://xxxxxxxx/toolbox_hacking/assets/angular.js:9170
completeRequest#http://xxxxxxxx/toolbox_hacking/assets/angular.js:9333
createHttpBackend/</xhr.onreadystatechange#http://xxxxxxxx/toolbox_hacking/assets/angular.js:9304
It turns out that my controller.js had
var Home = angular.module("Home", []);
In addition to
app.js having
var Home = angular.module("Home", []);
controller.js wiped our my customer filters

Resources