问题
My html is this:
<body ng-controller="MainCtrl as ctrl" class="bodyContainer">
<div ng-repeat="stuff in ctrl.stuffies">
here
</div>
This is my controller:
angular.module("AuthenticationApp", ["BaseApp"])
.controller("MainCtrl", ["$http", "$window", "BaseService", function($http, $window, BaseService) {
var self = this;
BaseService.fetch.stuffs(function() {
self.stuffies = BaseService.stuffies;
console.log(self.stuffies);
self.cerrorMessages = BaseService.cerrorMessages;
});
}]);
And this is my BaseApp:
angular.module("BaseApp", [])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}])
.config(['$locationProvider', function($locationProvider){
$locationProvider.html5Mode(true);
}])
.factory("BaseService", ["$http", "$window", function($http, $window) {
var self = this;
/* All functions which call fetch should have a callback function
* on the front-end which sets
* 1) a variable (i.e. stuffies etc.)
* 2) and BaseService.cerrorMessages. */
self.fetch = {
stuff: function(callback) {
$http.get("/stuffs/")
.then(function(response) {
self.stuffies = response.data;
callback();
}, function(response) {
self.accessErrors(response.data);
callback();
});
}
};
The problem is, even though it logs an item inside self.stuffies (when this line is run: console.log(self.stuffies);), here is not printed in the HTML. There doesn't seem to be anything inside ctrl.stuffies. I tried moving console.log(self.stuffies); outside of BaseService.fetch.stuffs(function() and it logs undefined. How do I get ctrl.stuffies to be BaseService.stuffies?
回答1:
There is no need to use callbacks with the $http service as it returns promises:
//.factory("BaseService", ["$http", "$window", function($http, $window) {
app.service("BaseService", ["$http", "$window", function($http, $window) {
//var self = this;
/* All functions which call fetch should have a callback function
* on the front-end which sets
* 1) a variable (i.e. stuffies etc.)
* 2) and BaseService.cerrorMessages. */
this.fetch = {
stuff: function() {
//vvvv RETURN the promise
return $http.get("/stuffs/")
.then(function(response) {
//vvvv RETURN the data
return response.data;
//self.stuffies = response.data;
//callback();
});//, function(response) {
// self.accessErrors(response.data);
// callback();
//});
}
};
});
There is no need to do anything with $http errors in the service. Errors will be carried forward automatically in the promise.
Then in the controller extract the data (or the error) from the promise:
/* REPLACE
BaseService.fetch.stuffs(function() {
self.stuffies = BaseService.stuffies;
console.log(self.stuffies);
self.cerrorMessages = BaseService.cerrorMessages;
});
*/
BaseService.fetch.stuffs
.then(function(data) {
self.stuffies = data;
console.log(self.stuffies);
}).catch(function(errorResponse) {
self.cerrorMessages = errorResponse.data;
});
For more information, see
AngularJS $http Service API Reference.
MDN JavaScript Reference - return Statement
I changed your service to a factory
and made it this:and used it this way:BaseService.fetch.stuffs() .then(function(data) { self.stuffs = data; console.log(self.stuffs); }).catch(function(errorResponse) { self.cerrorMessages = errorResponse.data; });Is this fine (using factory because there are other functions inside the factory as well and I don't want to have to change them all to services)?
Sorry, the factory is
self.fetch = { stuffs: function() { return $http.get("/stuffs/") .then(function(response) { return response.data; }); } };
Either a service or a factory will work. With a service, functions can be added by adding properties to the this context which is automatically returned (unless overridden with a return statement). With a factory, a return statement is manditory. Functions are added to the object returned. The choice is a question of style. They are both used the same way.
回答2:
You're using a factory like a service.
Have your factory self call (initialize) its self.fetch function, then upon construction of your controller, set the controller's stuffies variable equal to the factory's stuffies variable.
Edit:
If you only want some of the data initialized at once, you can self call only the functions you want to retrieve data initially.
You can then use a resolve in your routing to initialize more data when a specific route is hit.
来源:https://stackoverflow.com/questions/42940090/assigning-variable-from-a-factory-to-a-control-doesnt-work