Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

Suppose we have the following resource (using the ngResource module) which returns an array of JSON results:

app.factory('myApi', function($resource) {
    return $resource('/myApi/:param')
    // returns an array of json objects
});

And the following main controller:

app.controller('mainController', function(myApi) {
    var results = []
    var _init = function() {
        myApi.get({param: 1234}, function(data) {
            results = data.results
        });
    }

    _init();

    return {
        results: results
    }
});

I'd like to run an ng-repeat on the results.

<body ng-controller="mainController as main">
    <p ng-repeat="r in main.results">{{r.myResult}}</p>
</body>

I've confirmed that the resource is returning the correct results. However, using the above template, nothing appears.

I'm trying to accomplish this without using $scope and using the "Controller as" syntax. I'm also trying to keep my code clean and maintainable by not using tons of "this.___" in my controller objects (hence returning an object at the end of the controller definition).

What's the cleanest way to solve this problem? I've seen tons of solutions that use $scope, but I don't want to go back to using that object.

share|improve this question
    
you are overwriting your results variable with a new array, so main.results wont be referencing the same array anymore. Remove any previous elements from results, and then use results.push to put new elements onto the array. – Patrick Evans Apr 27 at 1:14

2 Answers 2

I was able to solve the problem by saving the reference to the current scope to the variable "vm":

app.controller('mainController', function(myApi) {
    var vm = this
    var results = []
    var _init = function() {
        myApi.get({param: 1234}, function(data) {
            vm.results = data.results
        });
    }

    _init();

    return {
        results: results
    }
});

Thus, the "results" object in the controller's scope is updated with the results of the resource call.

share|improve this answer

There are a couple things wrong with your example:

  1. First, when you set results in your init's callback your controller's results field is not referencing that new array. Since you are not using Angular's $scope you will need to maintain your controllers current state manually.
  2. Second, since your callback fires asynchronously it is not in the current digest loop. So, you need to manually force a digest when you update your data.

The example below fixes both issues with your controller:

app.controller('mainController', function($scope, myApi) {
    // Create our non-angular state/scope to return upfront so
    // we can modify its "results" when we get our data back.
    var _ctrlState = {
        results: null
    };

    var _init = function() {
        myApi.get({param: 1234}, function(data) {
            // Update the results field on our controller's state
            // object and force a scope digest.
            _ctrlState.results = data.results;
            $scope.$digest();
        });
    }    
    _init();

    return _ctrlState;
});

Here's a working fiddle (note, it has a fake myApi that returns data to fit your example template): http://jsfiddle.net/os1p0w64/

share|improve this answer
    
See the solution I posted - I saved the controllers scope into a variable and passed it into the callback. Worked like a charm. – cody Apr 27 at 4:34
    
@cody Sure. That is similar to my answer above, except you are using attaching your data to your controller instance the same as using this.__ (which I took from your question you wanted to avoid). The only issue with your answer is that you are returning an object but using this.__ (through a variable). You do not need to return anything, nor need that local results variable. Instead you should set vm.results = [] to initialize your results to an empty array. – rgthree Apr 27 at 14:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.