Variáveis ​​globais em AngularJS

Eu tenho um problema onde eu estou inicializando uma variável no escopo em um controlador. Em seguida, ele é alterado em outro controlador quando um usuário efetua login. Essa variável é usada para controlar itens como a barra de navegação e restringe o access a partes do site, dependendo do tipo de usuário, portanto é importante que ele mantenha seu valor. O problema com isso é que o controlador que o inicializa, é chamado novamente por angular de alguma forma e então redefine a variável de volta ao seu valor inicial.

Eu assumo que esta não é a maneira correta de declarar e inicializar variables ​​globais, bem, não é realmente global, então minha pergunta é qual é a maneira correta e existem alguns bons exemplos em torno desse trabalho com a versão atual do angular?

Se você quiser apenas armazenar um valor, de acordo com a documentação do Angular em provedores , você deve usar a receita do valor:

 var myApp = angular.module('myApp', []); myApp.value('clientId', 'a12345654321x'); 

Em seguida, use-o em um controlador como este:

 myApp.controller('DemoController', ['clientId', function DemoController(clientId) { this.clientId = clientId; }]); 

A mesma coisa pode ser alcançada usando um Provedor, Fábrica ou Serviço, já que eles são “apenas açúcar sintático sobre uma receita de provedor”, mas usar o Valor conseguirá o que você quer com uma syntax mínima.

A outra opção é usar o $rootScope , mas não é realmente uma opção, porque você não deve usá-lo pelas mesmas razões pelas quais você não deve usar variables ​​globais em outros idiomas. É aconselhável ser usado com moderação.

Como todos os escopos herdam de $rootScope , se você tiver uma variável $rootScope.data e alguém esquecer que os data já estão definidos e criar $scope.data em um escopo local, você terá problemas.


Se você quiser modificar este valor e mantê-lo em todos os seus controladores, use um object e modifique as propriedades, tendo em mente que o Javascript está passando por “cópia de uma referência” :

 myApp.value('clientId', { value: 'a12345654321x' }); myApp.controller('DemoController', ['clientId', function DemoController(clientId) { this.clientId = clientId; this.change = function(value) { clientId.value = 'something else'; } }]; 

Exemplo JSFiddle

Exemplo de “variables ​​globais” do AngularJS usando $rootScope :

O controlador 1 define a variável global:

 function MyCtrl1($scope, $rootScope) { $rootScope.name = 'anonymous'; } 

O controlador 2 lê a variável global:

 function MyCtrl2($scope, $rootScope) { $scope.name2 = $rootScope.name; } 

Aqui está um jsFiddle em funcionamento: http://jsfiddle.net/natefriedman/3XT3F/1/

No interesse de adicionar outra ideia ao wiki pool, mas e quanto aos módulos constant e de value AngularJS? Eu estou apenas começando a usá-los eu mesmo, mas parece-me que estas são provavelmente as melhores opções aqui.

Nota: até o momento em que escrevo, Angular 1.3.7 é o mais recente estável, acredito que estes foram adicionados em 1.2.0, mas não confirmaram isso com o changelog.

Dependendo de quantos você precisa definir, convém criar um arquivo separado para eles. Mas eu geralmente os defino antes do bloco .config() meu aplicativo para facilitar o access. Como esses módulos ainda são efetivamente eficazes, você precisará confiar na injeção de dependência para usá-los, mas eles são considerados “globais” para o módulo do aplicativo.

Por exemplo:

 angular.module('myApp', []) .value('debug', true) .constant('ENVIRONMENT', 'development') .config({...}) 

Então dentro de qualquer controlador:

 angular.module('myApp') .controller('MainCtrl', function(debug, ENVIRONMENT), { // here you can access `debug` and `ENVIRONMENT` as straight variables }) 

A partir da pergunta inicial, na verdade, parece que as propriedades estáticas são necessárias aqui, seja como mutável (valor) ou final (constante). É mais minha opinião pessoal do que qualquer outra coisa, mas acho que colocar itens de configuração em tempo de execução no $rootScope fica muito confuso, muito rapidamente.

 // app.js or break it up into seperate files // whatever structure is your flavor angular.module('myApp', []) .constant('CONFIG', { 'APP_NAME' : 'My Awesome App', 'APP_VERSION' : '0.0.0', 'GOOGLE_ANALYTICS_ID' : '', 'BASE_URL' : '', 'SYSTEM_LANGUAGE' : '' }) .controller('GlobalVarController', ['$scope', 'CONFIG', function($scope, CONFIG) { // If you wish to show the CONFIG vars in the console: console.log(CONFIG); // And your CONFIG vars in .constant will be passed to the HTML doc with this: $scope.config = CONFIG; }]); 

Em seu HTML:

 {{config.APP_NAME}} | v{{config.APP_VERSION}} 

Por favor, corrija-me se estiver errado, mas quando o Angular 2.0 for lançado, não acredito que $rootScope esteja disponível. Minha conjectura é baseada no fato de que $scope está sendo removido. Obviamente, os controladores ainda existirão, mas não na moda do controlador ng-controller Pense em injetar controladores em diretivas. À medida que o lançamento for iminente, será melhor usar serviços como variables ​​globais se você quiser um tempo mais fácil para mudar de verison 1.X para 2.0.

 localStorage.username = 'blah' 

Se você está garantido para estar em um navegador moderno. Embora saiba que seus valores serão todos transformados em seqüências de caracteres.

Também tem o benefício prático de ser armazenado em cache entre recarregamentos.

Você também pode usar a variável de ambiente $window para que uma variável global declare fora de um controller pode ser verificada dentro de um $watch

 var initWatch = function($scope,$window){ $scope.$watch(function(scope) { return $window.globalVar }, function(newValue) { $scope.updateDisplayedVar(newValue); }); } 

Sendo assim, o ciclo de digitação é mais longo com esses valores globais, por isso nem sempre é atualizado em tempo real. Eu preciso investigar esse tempo de digestão com essa configuração.

Acabei de encontrar outro método por engano:

O que eu fiz foi declarar um var db = null acima da declaração do aplicativo e depois modificá-lo no app.js e quando eu o app.js no controller.js eu consegui acessá-lo sem nenhum problema.Pode haver alguns problemas com isso método que eu não conheço, mas é uma boa solução, eu acho.

Tente isso, você não vai forçar a injeção de $rootScope no controlador.

 app.run(function($rootScope) { $rootScope.Currency = 'USD'; }); 

Você só pode usá-lo no bloco de execução porque o bloco de configuração não fornecerá o uso de $ rootScope.

Você também pode fazer algo assim

 function MyCtrl1($scope) { $rootScope.$root.name = 'anonymous'; } function MyCtrl2($scope) { var name = $rootScope.$root.name; }