Desenvolvimento

20 nov, 2014

Compartilhando $scope entre controladores com AngularJs

Publicidade

O Angular cria um objeto $scope para cada controlador. Temos também um $rootScope acessível a partir de todos os controladores. Mas podemos ter acesso a um $scope de um controlador a partir de outro controlador? A resposta é não. Além disso, se nosso aplicativo precisa acessar o $scope de outro controlador, provavelmente estamos fazendo algo errado e precisamos repensar o nosso problema. De qualquer forma, é possível acessar o $scope de outro controlador se o armazenarmos em um serviço. Vou mostrar um exemplo.

Imagine este pequeno exemplo:

<!doctype html>
<html ng-app="app">
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.18/angular.js"></script>
    <script src="app.js"></script>
</head>
<body>
 
<div ng-controller="OneController">
    <h2>OneController</h2>
    <button ng-click="buttonClick()">
        buttonClick on current scope
    </button>
</div>
 
<div ng-controller="TwoController">
    <h2>TwoController</h2>
    <button ng-click="buttonClick()">
        buttonClick on current scope
    </button>
</div>
</body>
</html>

Como podemos ver, definimos dois controladores: “OneController” e “TwoController”.

Esse é o aplicativo:

var app = angular.module('app', []);
 
app.controller('OneController', function ($scope) {
    $scope.variable1 = "One";
 
    $scope.buttonClick = function () {
        console.log("OneController");
        console.log("$scope::variable1", $scope.variable1);
    };
});
 
app.controller('TwoController', function ($scope) {
    $scope.variable1 = "Two";
 
    $scope.buttonClick = function () {
        console.log("TwoController");
        console.log("$scope::variable1", $scope.variable1);
    };
});

Se precisarmos acessar o $scope de outro controlador, nós precisamos armazenar esses scopes em um serviço. Por exemplo, com este serviço mínimo:

app.factory('Scopes', function ($rootScope) {
    var mem = {};
 
    return {
        store: function (key, value) {
            mem[key] = value;
        },
        get: function (key) {
            return mem[key];
        }
    };
});

E agora precisamos armazenar o $scope no serviço:

app.controller('OneController', function ($scope, Scopes) {
    Scopes.store('OneController', $scope);
    ...
});
app.controller('TwoController', function ($scope, Scopes) {
    Scopes.store('TwoController', $scope);
    ...
});

E agora podemos acessar outro $scope

Aqui o exemplo completo:

<!doctype html>
<html ng-app="app">
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.18/angular.js"></script>
    <script src="app.js"></script>
</head>
<body>
 
<div ng-controller="OneController">
    <h2>OneController</h2>
    <button ng-click="buttonClick()">
        buttonClick on current scope
    </button>
    <button ng-click="buttonClickOnTwoController()">
        buttonClick on TwoController's scope
    </button>
</div>
 
<div ng-controller="TwoController">
    <h2>TwoController</h2>
    <button ng-click="buttonClick()">
        buttonClick on current scope
    </button>
    <button ng-click="buttonClickOnOneController()">
        buttonClick on OneController's scope
    </button>
</div>
</body>
</html>

e app.js:

var app = angular.module('app', []);
 
app.run(function ($rootScope) {
    $rootScope.$on('scope.stored', function (event, data) {
        console.log("scope.stored", data);
    });
});
app.controller('OneController', function ($scope, Scopes) {
 
    Scopes.store('OneController', $scope);
 
    $scope.variable1 = "One";
 
    $scope.buttonClick = function () {
        console.log("OneController");
        console.log("OneController::variable1", Scopes.get('OneController').variable1);
        console.log("TwoController::variable1", Scopes.get('TwoController').variable1);
        console.log("$scope::variable1", $scope.variable1);
    };
 
    $scope.buttonClickOnTwoController = function () {
        Scopes.get('TwoController').buttonClick();
    };
});
app.controller('TwoController', function ($scope, Scopes) {
 
    Scopes.store('TwoController', $scope);
 
    $scope.variable1 = "Two";
 
    $scope.buttonClick = function () {
        console.log("TwoController");
        console.log("OneController::variable1", Scopes.get('OneController').variable1);
        console.log("TwoController::variable1", Scopes.get('TwoController').variable1);
        console.log("$scope::variable1", $scope.variable1);
    };
 
    $scope.buttonClickOnOneController = function () {
        Scopes.get('OneController').buttonClick();
    };
});
app.factory('Scopes', function ($rootScope) {
    var mem = {};
 
    return {
        store: function (key, value) {
            $rootScope.$emit('scope.stored', key);
            mem[key] = value;
        },
        get: function (key) {
            return mem[key];
        }
    };
});

Você também pode vê-lo rodando aqui.

***

Artigo traduzido pela Redação iMasters com autorização do autor. Publicado originalmente em http://gonzalo123.com/2014/09/08/sharing-scope-between-controllers-with-angularjs/