Roteador de interface angular: modos de exibição nesteds não funciona

Construindo um formulário de várias etapas (“assistente”). Estava seguindo este tutorial originalmente , que funcionou muito bem, mas agora estou tentando adaptá-lo para que a primeira etapa seja incorporada na página inicial, em vez de ser um estado separado. Não importa o que eu tente, não posso criar um caminho ui-sref que funcione. Eu sempre recebo:

Não foi possível resolver ‘.where’ do estado ‘home’

ou

Não foi possível resolver ‘wizard.where’ do estado ‘home’

ou

Não foi possível resolver ‘wizard.where @’ do estado ‘home’

… Mesmo que wizard.where@ funcione bem em

. Qual é a syntax correta?

Aqui estão os arquivos relevantes:

home.js (deixou os comentários intactos para que você possa ver vários methods que estou tentando):

 var wizard = { url: '/home/wizard', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard.tpl.html' }; angular.module( 'myApp.home', [ 'ui.router', 'ui.bootstrap', 'myApp.modal', 'angularMoment' ]) .config(function config( $stateProvider, $urlRouterProvider ) { $stateProvider .state( 'home', { url: '/home', views: { "main": { controller: 'HomeCtrl', templateUrl: 'home/home.tpl.html' }, "jumbotron": { controller: 'HomeCtrl', templateUrl: 'home/welcome.tpl.html' }, "wizard": wizard, "wizard.where": { url: '/home/wizard/where', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard-where.tpl.html', parent: wizard }, "wizard.what": { url: '/home/wizard/what', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard-what.tpl.html', parent: wizard }, "wizard.when": { url: '/home/wizard/when', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard-when.tpl.html', parent: wizard }, }, data: { pageTitle: 'Home' } }) // route to show our basic form (/wizard) // .state('wizard', { // url: '/wizard', // views: { // "main": { // controller: 'VendorsCtrl', // templateUrl: 'vendors/wizard.tpl.html' // } // }, // abstract: true, // //data: { pageTitle: 'Vendor Search' } // }) // nested states // each of these sections will have their own view // url will be nested (/wizard/where) // .state('wizard.where', { // url: '/where', // templateUrl: 'vendors/wizard-where.tpl.html' // }) // url will be /wizard/when // .state('wizard.when', { // url: '/when', // templateUrl: 'vendors/wizard-when.tpl.html' // }) // url will be /wizard/vendor-types // .state('wizard.what', { // url: '/what', // templateUrl: 'vendors/wizard-what.tpl.html' // }) ; // catch all route // send users to the form page $urlRouterProvider.otherwise('/home/wizard/where'); }) 

wizard.tpl.html :

 

{{ pageTitle }}

Answer the following three questions to search available vendors. All answers can be changed later.

wizard.where.tpl.html :

 

If left blank, vendors in all available locations will be shown.

Eu criei plunker de trabalho aqui

NOTA: Você deve ler mais sobre aninhamento de estado e exibições nomeadas. Porque o estado atual e a definição da visão estão simplesmente errados.

  • Estados nesteds e exibições aninhadas
  • Múltiplas exibições nomeadas

Em primeiro lugar, não devemos usar a definição de estado ONE com muitas views: {} . Mas devemos dividi-los em estados reais. Hierarquia terá três níveis

O primeiro nível – super root state

 .state( 'home', { url: '/home', views: { "main": { controller: 'HomeCtrl', templateUrl: 'home/home.tpl.html' }, } }) 

O segundo nível – wizzard, verifique se agora mudamos o URL. Nós herdaremos sua primeira parte de nossos pais (casa)

 .state("wizard", { parent: 'home', //url: '/home/wizard', url: '/wizard', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard.tpl.html' }) 

O terceiro nível – todos onde, o que, quando agora também herdará url. Eles não precisam definir pai, porque é parte de seus nomes

 .state( "wizard.where", { //url: '/home/wizard/where', url: '/where', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard-where.tpl.html', //parent: wizard }) .state( "wizard.what", { //url: '/home/wizard/what', url: '/what', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard-what.tpl.html', //parent: wizard }) .state( "wizard.when", { //url: '/home/wizard/when', url: '/when', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard-when.tpl.html', //parent: wizard }) 

O wizzard pai agora deve conter o destino de exibição sem nome ui-view=""

 

O atual wizard.tpl.html contém isto:

  

O sinal @ deve ser evitado, porque poderia ser usado para nomear a vista absulte – MAS dentro da definição de estado. Então, o que poderia funcionar é ui-view="someName

  

Agora, estes são ( no exemplo aqui ) ver o conteúdo da home.tpl

 

HOME

E wizzard.tpl

 

WIZZARD

Portanto, temos um destino de exibição sem nome dentro dos estados inicial e de assistente . Isso é muito útil, porque podemos usar a definição de estado de luz, sem views : {} object. E isso é sempre preferível caso não tenhamos várias visualizações.

Isso significa que essa definição de estado será corretamente injetada no modelo acima:

 // no views - search in parent for a ui-view="" ... .state( "wizard.when", { url: '/when', controller: 'VendorsCtrl', templateUrl: 'vendors/wizard-when.tpl.html', }) ... 

Verifique o documento:

Exibir nomes – relativos versus nomes absolutos

Nos bastidores, cada view recebe um nome absoluto que segue um esquema de viewname@statename , onde viewname é o nome usado na diretiva view e state name é o nome absoluto do estado, por exemplo, contact.item. Você também pode optar por escrever seus nomes de exibição na syntax absoluta.

Por exemplo, o exemplo anterior também pode ser escrito como:

 .state('report',{ views: { 'filters@': { }, 'tabledata@': { }, 'graph@': { } } }) 

Observe que os nomes das visualizações agora são especificados como nomes absolutos, ao contrário do nome relativo. Ele está segmentando as exibições “filters”, “tabledata” e “graph” localizadas no modelo raiz sem nome. Como não tem nome, não há nada seguindo o ‘@’. O modelo raiz sem nome é o seu index.html.

Chamando o estado do estado

Quando queremos onde o estado navega para quando, podemos usar o directiv ui-sref , mas ele deve conter o nome do estado, não exibir a convenção de nomenclatura

 // instead of this  

O motivo, que nesta hierarquia de três níveis usamos apenas nomes pai e filho (não grand pai 'home') , está oculto na definição de estado. Porque nós usamos isso:

 .state("wizard", { parent: 'home', 

Pai é apenas um pai, não faz parte do nome do estado. O que é bom em cenários como este (nós precisamos da raiz / grand pai para estabelecer algumas coisas comuns, mas o nome não é necessário para subestados)

Verifique o documento:

ui-sref

Uma diretiva que liga um link (tag ) a um estado. Se o estado tiver uma URL associada, a diretiva gerará e atualizará automaticamente o atributo href por meio do método $ state.href () . Clicar no link acionará uma transição de estado com parâmetros opcionais.
...

Você pode especificar opções para passar para $ state.go () usando o atributo ui-sref-opts . As opções são restritas à localização, inheritance e recarregamento.

ui-sref - string - 'stateName' pode ser qualquer estado absoluto ou relativo válido

[S] um passo é incorporado na página inicial em vez de ser um estado separado

Você deve tratar cada ui-view como um estado, mas declarar wizard.where como o estado padrão / index .

Observe que o tutorial usa $ urlRouterProvider para tornar o form/profile o estado padrão.

 // catch all route // send users to the form page $urlRouterProvider.otherwise('/form/profile'); 

Dessa maneira, no entanto, /form terminará como /form/profile .

Você pode, no entanto, criar um estado de URL vazio com pequenas modificações :

 // route to show our basic form (/form) .state('form', { url: '/form', templateUrl: 'form.html', controller: 'formController', abstract: true //<-- Declare parent as an abstract state. }) // nested states // each of these sections will have their own view // url will be nested (/form) .state('form.profile', { url: '', //<-- Empty string for "profile" state to override the /form abstract state templateUrl: 'form-profile.html' }) // catch all route // send users to the form page $urlRouterProvider.otherwise('/form'); //<-- Default state is empty 

@ radim-köhler também forneceu uma boa visão sobre as definições de roteador e estado da interface do usuário.