Jean-Michel Provencher Jean-Michel Provencher - 5 months ago 27
jQuery Question

TypeError: Cannot read property 'items' of undefined

I'm trying to calculate the subtotal of a a quote inside an angular js controller but i receive this error when I'm calling the function inside the html file.

angular.js:13550 TypeError: Cannot read property 'items' of undefined
at n.$scope.subtotal (quote.js:66)
at fn0 (eval at <anonymous> (angular.js:14432), <anonymous>:4:457)
at angular.js:15525
at n.$digest (angular.js:17064)
at n.$apply (angular.js:17337)
at l (angular.js:11572)
at H (angular.js:11778)
at XMLHttpRequest.u.onload (angular.js:11711)


My .js file looks like that

angular.module('canex')
.controller("QuoteController", ['$scope', '$routeParams', '$location', 'ProjectService', 'QuoteService', 'UploadService', 'ClientService', 'ItemService',
function ($scope, $routeParams, $location, projectService, quoteService, uploadService, clientService, itemService) {
$scope.clientId = $routeParams.clientId;

function _fetchItems() {
itemService.getQuoteItems($routeParams.quoteId)
.then(function (response) {
$scope.items = response.data;
}, $scope.httpErrorCallback);
}

$scope.subtotal = function () {
var subtotal = 0;
angular.forEach($scope.items.data, function (item) {
subtotal += item.quantity * item.rate;
});
return subtotal;
};

_fetchItems();


The part with
angular.forEach($scope.items.data, function (item) {
is what raises the TypeError, although the function seems to work properly.

and my HTML file looks like

<table id="quote-totals">

<tr>
<td colspan="2" class="blank"></td>
<td colspan="2" class="totals">{{ 'SUBTOTAL' | translate }}</td>
<td class="totals">
<div id="subtotal">{{ subtotal() | currency }}</div>
</td>
</tr>
<tr>
<td colspan="2" class="blank"></td>
<td colspan="2"
class="totals">{{ 'TPS' | translate }} {{ 'AT' | translate }} {{ quote.country_tax }}%
</td>
<td class="totals">
<div id="country-tax">{{ subtotal() * quote.country_tax * 0.01 | currency }}</div>
</td>
</tr>
<tr>
<td colspan="2" class="blank"></td>
<td colspan="2"
class="totals">{{ 'TVQ' | translate }} {{ 'AT' | translate }} {{ quote.province_tax }}%
</td>
<td class="totals">
<div id="province-tax">{{ subtotal() * quote.province_tax * 0.01 | currency }}</div>
</td>
</tr>
<tr>
<td colspan="2" class="blank"></td>
<td colspan="2" class="totals">{{ 'TOTAL' | translate }}</td>
<td class="totals">
<div id="total">{{ subtotal() + (subtotal() * quote.country_tax * 0.01) + (subtotal() * quote.province_tax * 0.01)| currency }}</div>
</td>
</tr>
</table>


The code works and calculate the subtotal but i receive the undefined error at every page refresh. I suppose it's trying to calcule the subtotal before $scope.items is loaded but I don't know to solve it.

Answer

It's because you're fetching the items asynchronously, and trying to use them in your template right away without initializing the value. Try adding $scope.items = []; somewhere in your controller. It will initialize the value to an empty array so that you don't get a type error, but an empty array looks like it shouldn't cause you any ill effects.

Comments