Como faço para compartilhar dados de escopo $ entre estados em angularjs ui-router?

Sem o uso de um serviço ou a construção de observadores no controlador pai, como se daria aos estados filhos access ao $scope do controlador principal.

  .state("main", { controller:'mainController', url:"/main", templateUrl: "main_init.html" }) .state("main.1", { controller:'mainController', parent: 'main', url:"/1", templateUrl: 'form_1.html' }) .state("main.2", { controller:'mainController', parent: 'main', url: "/2", templateUrl: 'form_2.html' }) 

Eu não sou capaz de acessar o escopo mainController no estado filho – ou melhor, eu estou recebendo outra instância desse escopo – não o que eu quero. Eu sinto que estou sentindo falta de algo simples. Existe uma opção de configuração de dados compartilhada no object de estado, mas não tenho certeza se isso deve ser usado para algo como isto.

Eu criei o plunker de trabalho , mostrando como usar o $scope e o UI-Router.

A definição do estado é inalterada:

 $stateProvider // States .state("main", { controller:'mainController', url:"/main", templateUrl: "main_init.html" }) .state("main.1", { controller:'mainController', parent: 'main', url:"/1", templateUrl: 'form_1.html' }) .state("main.2", { controller:'mainController', parent: 'main', url: "/2", templateUrl: 'form_2.html' }) 

Mas cada estado pode ter um controlador diferente. Por quê? porque cada view de cada estado obtém uma new instância do controller definido. Portanto, embora tenhamos mainController como o abaixo, podemos ter certeza de que, se 'main.2' para o estado 'main.2' ele será instanciado duas vezes.

 controller('mainController', function ($scope) { $scope.Model = $scope.Model || {Name : "xxx"}; }) 

Mas o que podemos ver aqui , é que verificamos se $scope.Model já existe … e se não (estado pai) , instanciamos com intance novo {Name : "xxx"} .

Bem, o que estou dizendo é: apenas o estado pai irá $scope.Model o $scope.Model . Todos os outros receberão isso já preenchido. Como? Bem, aqui está a resposta:

Herança de escopo somente pela hierarquia de exibição

Tenha em mente que as propriedades do escopo somente herdam a cadeia de estados se as exibições de seus estados estiverem aninhadas. Herança de propriedades de escopo não tem nada a ver com o aninhamento de seus estados e tudo a ver com o aninhamento de suas exibições (modelos).

É totalmente possível que você tenha estados nesteds cujos modelos preencham visualizações de ui em vários locais não nesteds em seu site. Nesse cenário, você não pode esperar acessar as variables ​​de escopo das exibições de estado pai nas exibições dos estados filhos.

Então, como indicado na documentação. Como nossas exibições filhas estão aninhadas na exibição pai, o escopo é herdado.

Entendendo os escopos

No AngularJS, um escopo filho normalmente é herdado prototipicamente de seu escopo pai.

Tendo uma ‘.’ em seus modelos, garantirá que a inheritance prototípica esteja em jogo.

 // So, use  // rather than . 

E é isso. Recebemos inheritance das visualizações do UI-Router de UI-Router do UI-Router e dos escopos angulares e porque usamos inteligentemente um tipo de referência ( Model ), ou seja, temos '.' ponto na definição ng-model – podemos compartilhar dados agora

NOTA: tendo ponto ‘.’ no ng-model="Model.PropertyName significa simplesmente que existe um Model {} object de reference Model {} com alguma propriedade: PropertyName

Confira o exemplo de trabalho aqui

Você pode obter todo o escopo através de $ rootScope . Se você precisa apenas de parte do escopo, o ui-roteador tem um recurso de dados personalizados .

Veja como fazer um formulário de várias etapas. Eu precisava das rotas para conter informações sobre seus passos no stream.

Primeiro, eu tenho algumas rotas com o roteador UI:

  // Sign UP routes .state('sign-up', { abstract: true, url: '/sign-up', controller: 'SignupController', templateUrl: 'sign-up/index.html', }) .state('sign-up.start', { url: '-start', templateUrl: 'sign-up/sign-up.start.html', data: { step: 0, title: 'Welcome to Mars!', }, }) .state('sign-up.expertise', { url: '-expertise', templateUrl: 'sign-up/sign-up.expertise.html', data: { step: 1, title: 'Your Expertise'}, }) 

Aviso prévio:

  • o elemento de data em cada rota.
  • O estado abstract possui SignupController . Esse é o único controlador para este formulário de várias etapas. O abstract não é obrigatório, mas faz sentido para este caso de uso.

SignupController.js

 angular.module('app').controller('SignupController', function($scope, $state) { $scope.state = $state; }); 

Aqui nós obtemos o $state do ui-roteador e o colocamos no $scope

Aqui está o modelo principal ‘inscrever-se / index.html’:

 

{{state.current.data.title}}

This is a multi-step-progress control {{state.current.data.step}}

Os modelos filhos podem ser o que quiserem.

A idéia é que você use o escopo em parent-> child inheritance:

  .state("main", { controller:'mainController', abstract: true, url:"/main", templateUrl: "main_init.html" }) .state("main.1", { controller:'mainController1', parent: 'main', url:"/1", templateUrl: 'form_1.html' }) .state("main.2", { controller:'mainController2', parent: 'main', url: "/2", templateUrl: 'form_2.html' }) 

Do que o uso é simples, você tem 3 controladores, um é compartilhado (mainController) e cada visão tem o seu próprio.

Se você estiver usando visualizações aninhadas, simplesmente não escreva nenhum outro Controlador. Dessa forma, eles compartilharão os mesmos dados do controlador.

 .state("main", { url: "/main", templateUrl: "templates/Ders", controller: "DersController as DersC" }).state("main.child1", { url: "/child1", templateUrl: "templates/Ders/child1" }).state("main.child2", { url: "/child2", templateUrl: "templates/Ders/child2" }) 

A solução mais simples não é agrupar variables ​​compartilhadas em um serviço que você pode acessar em todos os controladores? …