Assigning variable from a factory to a control doe

2019-09-15 11:42发布

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?

2条回答
\"骚年 ilove
2楼-- · 2019-09-15 11:58

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


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.

查看更多
迷人小祖宗
3楼-- · 2019-09-15 12:02

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.

查看更多
登录 后发表回答