Reputation: 65
Hello guys I have the following code here :
angular.module('todomvc')
.factory('todoStorage', function ($http) {
'use strict';
var STORAGE_ID = 'todos-angularjs';
return {
get: function () {
$http({method: 'GET', url: '/api/todo.php'}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
return JSON.stringify(data);
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
},
put: function (todos) {
debugger;
localStorage.setItem(STORAGE_ID, JSON.stringify(todos));
}
};
});
as well as
angular.module('todomvc')
.controller('TodoCtrl', function TodoCtrl($scope, $routeParams, $filter, todoStorage, $http) {
'use strict';
var todos = $scope.todos = todoStorage.get();
$scope.newTodo = '';
$scope.editedTodo = null;
$scope.$watch('todos', function (newValue, oldValue) {
$scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
$scope.completedCount = todos.length - $scope.remainingCount;
$scope.allChecked = !$scope.remainingCount;
if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
todoStorage.put(todos);
}
}, true);
The issue i have is that the HTTP request is not completing before the code at $scope.$watch is being executed therefore it is calling .length on undefined. I am a total n00b to Angular and wanted to use this TodoMVC to get it working however im not sure what i can do to halt the whole process instead of wrapping the rest of the code within the success callback from the http request.
Thanks in advance
Upvotes: 0
Views: 1419
Reputation: 56
$http
is wrapped in a promise. You could return the promise from the service:
return $http({method: 'GET', url: '/api/todo.php'})
In the controller you can use then
method to specify the behaviour when the request is completed:
$scope.newTodo = '';
$scope.editedTodo = null;
todoStorage.get().then(function(result) {
$scope.todos = result.data;
$scope.$watch('todos', function (newValue, oldValue) {
$scope.remainingCount = $filter('filter')($scope.todos, { completed: false }).length;
$scope.completedCount = todos.length - $scope.remainingCount;
$scope.allChecked = !$scope.remainingCount;
if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
todoStorage.put($scope.todos);
}
}, true);
});
A good example about how to chain promises:
http://codepen.io/willh/pen/fCtuw
Upvotes: 0
Reputation: 23211
use this code:
angular.module('todomvc')
.factory('todoStorage', function ($http) {
'use strict';
var STORAGE_ID = 'todos-angularjs';
return {
get: function () {
return $http({method: 'GET', url: '/api/todo.php'})
},
put: function (todos) {
debugger;
localStorage.setItem(STORAGE_ID, JSON.stringify(todos));
}
};
});
angular.module('todomvc')
.controller('TodoCtrl', function TodoCtrl($scope, $routeParams, $filter, todoStorage, $http) {
'use strict';
$scope.newTodo = '';
$scope.editedTodo = null;
todoStorage.get()
.then(function(d){
$scope.todos=d;
})
.catch(function(e){
console.error(e);
})
$scope.$watch('todos', function (newValue, oldValue) {
$scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
$scope.completedCount = todos.length - $scope.remainingCount;
$scope.allChecked = !$scope.remainingCount;
if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
todoStorage.put(todos);
}
}, true);
Upvotes: 0
Reputation: 123739
Issue
get
method of your factory, and use $http.then
instead of http's custom promise method success
.In your factory
return {
get: function () {
return $http({method: 'GET', url: '/api/todo.php'}). //Return here
then(function(response) { //
return response.data;
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
},
In your controller:-
var todos;
todoStorage.get().then(function(data) {
todos = $scope.todos = data
});
and
$scope.$watch('todos', function (newValue, oldValue) {
if(!newValue) return;
$scope.remainingCount = $filter('filter')(todos, { completed: false }).length;
$scope.completedCount = todos.length - $scope.remainingCount;
$scope.allChecked = !$scope.remainingCount;
if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
todoStorage.put(todos);
}
}, true);
Upvotes: 2