Deepsy
Deepsy

Reputation: 3810

AngularJS: ng-repeat with dynamic data

I'm building a simple AngularJS app, but I couldn't solve a problem regarding services, ng-repeat and dynamically added data.

What I'm trying to do

My page is splitted into few countrollers. In the homeController I have a text field and a button. When I press the button I'm doing an API call to the server, the server returns JSON and I'm setting the data to Storage service. In this part everything is OK - The server returns data as it should and the data is setted to the service and I'm getting console.log('Data set!'); in the Storage service. In the second controller ( slidesController ) I'm having a ng-repeat

<div ng-controller="slidesCtrl">
    <div ng-repeat="current in paragraphs"> test </div>
</div>

And as you can see in my code below, paragraphs is binded to Storage.data value in slidesCtrl

So, when a user enter something in the box and press the button (homeCtrl), the server should pass the returned data to Storage service and render the data using ng-repeat (slideCtrl). If I hardcode the data in Storage server with [2, 3, 4, 5] for example, everything is ok ( I'm getting test 4 times, because of ng-repeat ), but if the data is taken with api call, ng-repeat isn't working.

Code

App.controller('homeCtrl', function ($scope, $http, Api) {...

    $scope.onprocess = function () {
        $scope.loading = true;

        Api(.....);
    }
});

App.controller('slidesCtrl', function ($scope, Storage) {


    $scope.paragraphs = Storage.data.paragraphs; // NOT WORKING IF DATA IS DYNAMICALLY ADDED

    $scope.paragraphs = Storage.test; // IF DATA IS PREDEFINED EVERYTHING IS FINE


});

App.factory('Api', function ($http, Storage) {
    return function (data) {
        $http.post('/api', {
            url: data.url,
            analyze: 0
        }).success(function (res) {....
            Storage.set(res);....
        }).error(function () {....
        });
    };
});

App.factory('Storage', function () {
    var output = {};

    var set = function (data) {
        output = data;
        console.log('Data set!');
    };

    return {
        set: set,
        data: output,
        test: [1, 2, 3]
    };
});

Upvotes: 1

Views: 2377

Answers (3)

Deepsy
Deepsy

Reputation: 3810

I found

angular.copy(data, output);

as solution.

You can see more information on this topic Sharing dynamic data between two controllers with service AngularJS

Thanks to everyone.

Upvotes: 1

satchmorun
satchmorun

Reputation: 12467

The problem is with how you've defined your Storage service.

In the set function, you're assigning directly to the output local variable, which will not automatically update the data property of the object the factory returns.

To illustrate the problem:

var output = {foo: 1, bar: 2};
function set(somenewdata) {
  output = somenewdata;
}
var obj = {data: output};
// obj == {data: {foo: 1, bar: 2}}

set({baz: 3});

// output == {baz: 3}
// but, obj == {data: {foo: 1, bar: 2}}

So if you change your Storage service to something like:

App.service('Storage', function() {
  this.data = {};
  this.set = function(newdata) {
    this.data = newdata;
  };
});

When a controller binds a property to Storage.data, the data will actually be updated.

Upvotes: 0

Abilash
Abilash

Reputation: 6089

I suspect that this is due to the lag in a AJAX call and angular executes the service before a AJAX call. As none of the scopes are changing, angular is not detecting a change and hence its not reflecting on your

Possible Solution

Use a getter in Storage service to get the paragraphs and call that getter method from slidesCtrl, like this.

App.controller('slidesCtrl', function($scope, Storage) {
    $scope.paragraphs = Storage.getParagraphs();
});

And in your service, you can use it like this.

App.factory('Storage', function() {
    var output = {};

    var set = function(data) {
        output = data;
        console.log('Data set!');
    };

    return {
        set: set,
        getParagraphs: function () {
            return output && output.paragraphs;
        }
    };
});

Upvotes: 0

Related Questions