AngularJS ng-table cannot set property '$data' of null
angularjs, coffeescript, ngtable
Solution
Can you show the code in your controller where you initialize ngTableParams?
Problem is `ng-table` uses `ngTableController` to set the `$scope` for `ngTableParams`. Since you are unit testing you wont have a `ngTableController` so `$scope` of `ngTableParams` will be null. You should manually set `$scope` of `ngTableParams` in your unit test. Try something similar to this JS (really dislike coffeescript, so convert to your needs):
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
ctrl = $controller('DebtorsController', {
$scope: scope,
$location: $location
});
scope.tableParams.settings().$scope = scope;
}));
Assuming you have something like the following in your controller where you initialize your `ngTableParams`:
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
total: data.length, // length of data
getData: function($defer, params) {
$defer.resolve(data.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
Problem
I've just started using ng-table and I'm trying to test it through jasmine unit tests (not sure if this is the best way to test my controllers) and I keep running into this error; ``` TypeError: Cannot set property '$data' of null at project/vendor/assets/javascripts/ng-table-0.3.1/ng-table.src.js:396:55 at C (project/vendor/assets/javascripts/angular-min.js:92:375) at project/vendor/assets/javascripts/angular-min.js:94:28 at h.$eval (project/vendor/assets/javascripts/angular-min.js:102:308) at h.$digest (project/vendor/assets/javascripts/angular-min.js:100:50) at h.$apply (project/vendor/assets/javascripts/angular-min.js:103:100) at f (project/vendor/assets/javascripts/angular-min.js:67:98) at handleResponse (project/vendor/assets/javascripts/angular-mocks.js:1160:9) at Function.$httpBackend.flush (project/vendor/assets/javascripts/angular-mocks.js:1491:26) at null.<anonymous> (project/spec/javascripts/unit/debtors_controller_spec.js.js:50:24) ``` Here is where I setup the ngTableParams in my controller ``` # Setup ng-table with defaults and data $scope.tableParams = new ngTableParams({ page: 1, count: 10, sorting: { code: 'asc'} }, { # data is created by ngTableParams total: 0, # ng-table will ask for updated data, this is where it gets it from. getData: ($defer, params) -> # Go get a list of debtors Debtor.query {}, (data) -> # Once successfully returned from the server with my data process it. params.total(data.length) # Filter filteredData = (if params.filter then $filter('filter')(data, params.filter()) else data) # Sort orderedData = (if params.sorting then $filter('orderBy')(filteredData, params.orderBy()) else data) # Paginate $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count())) }) ``` Here is the jasmine test ``` # ================================================================================ # Delete tests # ================================================================================ describe "destroy", -> beforeEach(inject ( ($controller, $rootScope, $location, $state, $httpBackend) -> ctrl = $controller('DebtorsController', { $scope: @scope, $location: $location }) )) it "gets new listing", -> @scope.debtors = [{id: 1, name: "Good guys"}, {id: 2, name: "John"}] @httpBackend.whenDELETE('/clients/1').respond(200) @httpBackend.whenGET('/debtors').respond(200, [{name: "John"}]) @scope.destroy(1) @httpBackend.flush() expect(@scope.debtors[0].name).toEqual('John') ``` Here is my code for deleting (which works) ``` # -------------------------------------------------------------------------------- # Delete # -------------------------------------------------------------------------------- $scope.destroy = (id) -> Client.delete id: id , (response) -> # Success flash("notice", "Client deleted", 2000) $scope.tableParams.reload() # Reload ng-table data, which will get a new listing from the server. , (response) -> # Failure ```