Sync issues when sharing objects with Factory and $watch

Asked

Viewed 195 times

0

I am trying to make a list of places by neighborhood. This data comes from different Urls:

www.example.com/api/lugares/bairro/1

www.example.com/api/lugares/bairro/2

the ID neighborhood is generated in a controller BairrosCtrl, which is where the user selects the neighborhood:

app.controller('BairrosCtrl', function($scope, selectedBairro, $location) {
    $scope.escolhaLugar = function(bairro) {
        $scope.$watch('bairro', function(newBairro) {
            if(newBairro) {
                selectedBairro.set(newBairro);
            }
        });
        $location.path('/lugares/');
    };
});

Note that the neighborhood is passed by parameter in the function escolhaLugar(bairro);

Using the Factory selectedBairro to try share the neighborhood object i create: a variable to initialize, a GET method and another SET:

app.factory('selectedBairro', function(){
    var bairro = {}
    return {
        set: function(bairroSelecionado) {
            bairro = bairroSelecionado;
        },
        get: function() {
            return bairro;
        }
    };
});

To try to consume the dice shared coming from the GET function I use the following function ($watch) in the controller LugaresCtrl:

app.controller('LugaresCtrl', function($scope, serviceLugares, $location, selectedBairro) {
    $scope.$watch(function() {
        return selectedBairro.get();
    }, function(newBairro) {
        if(newBairro) {
            $scope.bairro = newBairro;
            debugger; /*DEBUGGER 1*/
        }
    });
    debugger; /*DEBUGGER 2*/
    serviceLugares.getLugares($scope.bairro.id, function(data) {
        $scope.lugares = data.lugares;
    });
});

Seeing that $scope.bairro = newBairro i pass $scope.bairro.id by parameter to concatenate with the rest of the URL in the Factory serviceLugares, who is responsible for the $http request that accesses the API:

app.factory('serviceLugares', function($http){
    var lugaresList,
        obj = {};
    obj = {
        getLugares:function(id, callback) {
            if(lugaresList) {
                callback(lugaresList);
                return false;
            } 
            else {
                $http({
                    method: 'GET',
                    url: 'http://www.example.com/api/lugares/bairro/' + id
                }).success(function(data) {
                    obj.saveLugares(data);
                    callback(data);
                })
            }
        },
        saveLugares:function(data) {
            lugaresList = data;
        }
    }
    return obj;
});

In LugaresCtrl we have 2 debugger;. In DEBUGGER 1 the value of $scope.bairro is correct. However, in DEBUGGER 2 $scope.bairro does not exist. BECAUSE DEBUGGER 2 SHALL BE EXECUTED BEFORE DEBUGGER 1.

Somebody give me a hand?

  • It’s not because you put a $watch in bairro that it will be initialized. Hence the divergence between the debuggers. The DEBUGGER 2 is executed on controller startup. An external controller or attribute must initialize $scope.bairro why DEBUGGER 2 displays a value other than undefined.

  • I don’t know if I got it right, but I’ve tried using $scope.bairro = {}; to initialize the variable, but its value does not change, that is, in the DEBUGGER 2 she is a Object {} emptiness.

  • Looking at it better, I see that the DEBUGGER 2 is executed before the DEBUGGER 1. So, it will never take time to update the object to use it in the getLugares(id, callback). And now? :(

  • @Wineusgobboa.deOliveira So much is that using {{barrio.id}} in view he displays the ID. That is, neighborhood was updated in a timely manner to use the bind, but not to use in controller.

  • Exactly, as the DEBUGGER 2 runs on startup, it runs before the $watch. Not knowing more about your program is a bit complicated to answer precisely, but I believe it is possible to use ngInit passing the neighborhood as a parameter.

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.