Estou tentando compartilhar dados entre controladores. O caso de uso é um formulário de várias etapas; os dados inseridos em uma entrada são posteriormente utilizados em vários locais de exibição fora do controlador original. Código abaixo e em jsfiddle aqui .
HTML
<div ng-controller="FirstCtrl">
<input type="text" ng-model="FirstName"><!-- Input entered here -->
<br>Input is : <strong>{{FirstName}}</strong><!-- Successfully updates here -->
</div>
<hr>
<div ng-controller="SecondCtrl">
Input should also be here: {{FirstName}}<!-- How do I automatically updated it here? -->
</div>
JS
// declare the app with no dependencies
var myApp = angular.module('myApp', []);
// make a factory to share data between controllers
myApp.factory('Data', function(){
// I know this doesn't work, but what will?
var FirstName = '';
return FirstName;
});
// Step 1 Controller
myApp.controller('FirstCtrl', function( $scope, Data ){
});
// Step 2 Controller
myApp.controller('SecondCtrl', function( $scope, Data ){
$scope.FirstName = Data.FirstName;
});
Qualquer ajuda é muito apreciada.
javascript
angularjs
johnkeese
fonte
fonte
Respostas:
Uma solução simples é fazer com que sua fábrica retorne um objeto e permita que seus controladores trabalhem com uma referência ao mesmo objeto:
JS:
HTML:
Demonstração: http://jsfiddle.net/HEdJF/
Quando os aplicativos ficam maiores, mais complexos e difíceis de testar, você pode não querer expor o objeto inteiro da fábrica dessa maneira, mas, em vez disso, conceder acesso limitado, por exemplo, através de getters e setters:
Com essa abordagem, cabe aos controladores consumidores atualizar a fábrica com novos valores e observar as alterações para obtê-los:
HTML:
Demo: http://jsfiddle.net/27mk1n1o/
fonte
return { FirstName: '' };
ou retornar um objeto contendo métodos que interagem com um objeto, não seria preferível retornar uma instância de uma classe (function
) para que, quando você o use, ele tenha um tipo específico e não seja apenas um objeto{}" ?newValue !== oldValue
verificação porque o Angular não executa a função se o oldValue e o newValue forem os mesmos. A única exceção é se você se preocupa com o valor inicial. Veja: docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchEu prefiro não usar
$watch
para isso. Em vez de atribuir todo o serviço ao escopo de um controlador, você pode atribuir apenas os dados.JS:
HTML:
Como alternativa, você pode atualizar os dados do serviço com um método direto.
JS:
fonte
Existem várias maneiras de compartilhar dados entre controladores
Explicação de cada método:
Eu não vou explicar como já foi explicado por alguém
usando
$state.go
$stateparam
funciona de maneira semelhante a$state.go
, você o passa como objeto do controlador emissor e coleta no controlador receptor usando stateparamusando
$rootscope
(a) envio de dados do filho para o controlador pai
(b) enviar dados do pai para o controlador filho
fonte
Criei uma fábrica que controla o escopo compartilhado entre o padrão do caminho da rota, para que você possa manter os dados compartilhados apenas quando os usuários estiverem navegando no mesmo caminho pai da rota.
Portanto, se o usuário for para outro caminho de rota, por exemplo '/ Support', os dados compartilhados para o caminho '/ Customer' serão automaticamente destruídos. Mas se, em vez disso, o usuário seguir para caminhos 'filhos', como '/ Customer / 1' ou '/ Customer / list', o escopo não será destruído.
Você pode ver uma amostra aqui: http://plnkr.co/edit/OL8of9
fonte
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ ... })
se você tem ui.routerExistem várias maneiras de compartilhar dados entre controladores
Como sabemos
$rootscope
não é o caminho preferível para transferência ou comunicação de dados, pois é um escopo global disponível para toda a aplicaçãoPara compartilhamento de dados entre controladores Js angulares, serviços angulares são práticas recomendadas, por exemplo.
.factory
,.service
Para referência
Em caso de transferência de dados de pai para controlador de criança que você pode dados dos pais diretamente de acesso em controlador de criança através
$scope
Se você estiver usando
ui-router
, então você pode usar$stateParmas
para passar parâmetros URL comoid
,name
,key
, etc$broadcast
também é uma boa maneira de transferir dados entre controladores de pai para filho e$emit
transferir dados de controladores filho para paiHTML
JS
Consulte o link fornecido para saber mais sobre
$broadcast
fonte
Solução mais simples:
Eu usei um serviço AngularJS .
Etapa 1: Criei um serviço AngularJS chamado SharedDataService.
Etapa 2: Crie dois controladores e use o serviço criado acima.
Etapa 3: basta usar os controladores criados na exibição.
Para ver a solução funcional para esse problema, pressione o link abaixo
https://codepen.io/wins/pen/bmoYLr
arquivo .html:
fonte
FirstCtrl
é pai e recebe uma promessa de queSecondCtrl
(filho) também precisará? Não quero fazer duas chamadas de API. Obrigado.Existe outra maneira de usar $ watch, usando angular.copy:
fonte
Existem várias maneiras de fazer isso.
Eventos - já explicados bem.
ui router - explicado acima.
*
*
fonte
Não sei onde peguei esse padrão, mas para compartilhar dados entre controladores e reduzir o escopo $ rootScope e $, isso funciona muito bem. É uma reminiscência de uma replicação de dados em que você tem editores e assinantes. Espero que ajude.
O serviço:
O Controlador que está obtendo os novos dados, que é o Publicador, faria algo assim.
O Controlador que também está usando esses novos dados, chamados de Assinante, faria algo assim ...
Isso funcionará para qualquer cenário. Portanto, quando o controlador primário é inicializado e obtém dados, ele chamaria o método changeData, que transmitia isso para todos os assinantes desses dados. Isso reduz o acoplamento de nossos controladores entre si.
fonte
sharedDataEventHub.changeData(newData)
sharedDataEventHub.changeData(newData)
filho ou o controlador que depende desses dados teria em algum lugar do corpo do controlador o seguinte:sharedDataEventHub.onChangeData($scope, function(obj) { vm.myObject = obj.data; });
Se você usou a interface do usuário -Router isso pode ser injetado na configuração do estado.Basta fazer isso de forma simples (testada na v1.3.15)
fonte
dummy
é global para os dois controladores, em vez de compartilhado de maneira mais modular por herança com $ scope ou controllerAs ou usando um serviço.