Richard Le Mesurier
Richard Le Mesurier

Reputation: 29722

ng-repeat binding breaks with Parse.Cloud.run()

To summarise the problem:


My HTML is simple - I use ng-repeat to output characters from an array in my controller:

<body ng-controller="MainCtrl as main">

    <div ng-repeat="char in main.chars">
        {{char}}
    </div>
</body>

To populate this array, I have 2 factory services.

Both of these are succeeding, and expose a result using a Promise i.e. .then(...)

app.factory('httpFactory', function($http) {
    return {
        getArray: function () {
            return $http.get('/data/beaches.json').then(
                function(response){
                    var array = ["Y", "e", "s"];
                    return array;
                });
        }
    };
});

app.factory('parseFactory', function() {
    return {
        getArray: function () {
            return Parse.Cloud.run('hello').then(
                function(response){
                    console.log(response);
                    var array = ["N", "o"];
                    return array;
                });
        }
    };
});

Note that in this example, I am returning hard-coded values in the promises, to rule out any issues with the webservices themselves.

There is nothing special about the Parse Cloud function. It is from the basic template - function hello correctly returns the expected "Hello, world!".


My controller, MainCtrl is very simple. I instantiate the chars array with an initial value.

I call into each factory service in turn, using the return values to update my chars array, which I log out after the update is made.

The call to httpFactory.getArray() as this works exactly as expected:

The call to parseFactory.getArray() works mostly as expected:

But the bound HTML display does not change.

Here is my controller:

app.controller('MainCtrl', ['httpFactory', 'parseFactory', function(httpFactory, parseFactory){
    var main = this;
    main.chars = ["I", "n", "i", "t"];

    // httpFactory.getArray().then(function(arrHttp){
    //     main.chars = arrHttp;
    //     console.log("HTTP --> " + main.chars);
    // });

parseFactory.getArray().then(function(arrParse){
    main.chars = arrParse;
    console.log("PARSE -> " + main.chars);
});

According to the documentation, Parse.Cloud.run() supports Promises. From the console log output, that seems to be the case.

But the bound output doesn't update.

Is this an issue with AngularJS, Parse, or the way I'm using them?

(full code can be found here)

Demo Here


Update

I have logged this issue with Parse as a bug. Will update this post with feedback from their side.

Upvotes: 1

Views: 95

Answers (2)

Richard Le Mesurier
Richard Le Mesurier

Reputation: 29722

Instead of calling Parse.Cloud.run(), use their REST API for calling Cloud Functions.

They give the following example code:

curl -X POST \
  -H "X-Parse-Application-Id: 4vwhWtM5Sf3ExRvXMkRI04jJj8r2ZETuBQYhiYGo" \
  -H "X-Parse-REST-API-Key: EX6MWjSEblsrHsJCqBZ1AevuTKz0ZlWLHPMloZqD" \
  -H "Content-Type: application/json" \
  -d '{}' \
  https://api.parse.com/1/functions/hello

Based on that, I have modified parseFactory to use $http instead of Parse.Cloud.run():

app.factory('parseFactory', function($http) {
    return {
        getArray: function () {
            var request = {
                method: 'POST',
                url: 'https://api.parse.com/1/functions/hello',
                headers: {
                    'X-Parse-Application-Id': '4vwhWtM5Sf3ExRvXMkRI04jJj8r2ZETuBQYhiYGo',
                    'X-Parse-REST-API-Key': 'EX6MWjSEblsrHsJCqBZ1AevuTKz0ZlWLHPMloZqD',
                },
                data: {},
            };

            var parsePromise = $http(request).then(
                function(response){
                    console.log(response);
                    var array = ["F", "i", "x", "e", "d"];
                    return array;
                });
            return parsePromise;
        }
    };
});

This works exactly as expected.

Upvotes: 1

Pankaj Parkar
Pankaj Parkar

Reputation: 136154

I don't understand this weird behavior, but binding started working after adding $scope dependency inside MainCtrl controller

Code

app.controller('MainCtrl', ['httpFactory', 'parseFactory', '$scope',
  function(httpFactory, parseFactory, $scope) {

Demo Plunkr

Upvotes: 1

Related Questions