角UI路由器:嵌套视图不工作 [英] Angular-UI Router: Nested Views Not Working

查看:124
本文介绍了角UI路由器:嵌套视图不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

建立一个多步骤的形式(向导)。最初以下本教程,这伟大的工作,但我现在正在努力适应这么一步一被嵌入的网页上,而不是一个独立的国家。不管我怎么努力,我不能创建,将工作一个 UI-SREF 路径。我总是得到:


  

无法从国家解决'。凡'家'



  

无法解析从国家wizard.where'家'



  

无法解析wizard.where @从国家的家


...即使 wizard.where @ 工作正常<格UI视图=wizard.where @>< / DIV> 。什么是正确的语法?

下面是相关文件:

home.js (左意见完好无损,所以你可以看到我在尝试各种方法):

  VAR向导= {
  网址:'/家庭/巫师,
  控制器:'VendorsCtrl',
  templateUrl:供应商/ wizard.tpl.html
};angular.module('myApp.home',[
  ui.router',
  ui.bootstrap',
  myApp.modal',
  angularMoment
])的.config(配置功能($ stateProvider,$ urlRouterProvider){
  $ stateProvider
    .STATE('家',{
      网址:'/家,
      观点:{
        主:{
          控制器:'HomeCtrl',
          templateUrl:家/ home.tpl.html
        },
        超大屏幕:{
          控制器:'HomeCtrl',
          templateUrl:家/ welcome.tpl.html
        },
        向导:精灵,
        wizard.where:{
          网址:'/家庭/精灵/在哪里,
          控制器:'VendorsCtrl',
          templateUrl:供应商/精灵where.tpl.html',
          父:精灵
        },
        wizard.what:{
          网址:'/家庭/精灵/什么,
          控制器:'VendorsCtrl',
          templateUrl:供应商/精灵what.tpl.html',
          父:精灵
        },
        wizard.when:{
          网址:'/家庭/精灵/时',
          控制器:'VendorsCtrl',
          templateUrl:供应商/精灵when.tpl.html',
          父:精灵
        },
      },
      数据:{PAGETITLE:'家'}
    })    //路线,以显示我们的基本形式(/精灵)
    // .STATE(向导,{
    // URL:/巫师,
    //观点:{
    //主:{
    //控制器:'VendorsCtrl',
    // templateUrl:供应商/ wizard.tpl.html
    //}
    //},
    //摘要:真实,
    // //数据:{PAGETITLE:供应商搜索'}
    //})    //嵌套的状态
    //每个部分都会有自己的看法
    // URL将嵌套(/精灵/在哪里)
    // .STATE('wizard.where',{
    // URL:/在哪里,
    // templateUrl:供应商/精灵where.tpl.html
    //})    // URL会/精灵/时
    // .STATE('wizard.when',{
    //网址:'/时',
    // templateUrl:供应商/精灵when.tpl.html
    //})    // URL会/精灵/供应商类型
    // .STATE('wizard.what',{
    // URL:/什么,
    // templateUrl:供应商/精灵what.tpl.html
    //})
    ;    //捕捉所有航线
    //用户发送到窗体页
    $ urlRouterProvider.otherwise('/家庭/精灵/在哪里');
})

wizard.tpl.html

 < D​​IV CLASS =超大屏幕vendate精灵NG控制器=VendorsCtrl为vendorsCtrl>
  <头类=页面标题>
    < H1> {{} PAGETITLE}< / H1>
    < P>回答以下三个问题,以搜索可用的供应商。所有的答案都可以在以后改变< / P>    <! - 链接到我们的使用相对路径嵌套的状态 - >
    <! - 添加活动类,如果国家我们的UI,SREF匹配 - >
    < D​​IV ID =状态,按钮级=TEXT-中心>
      &下;一个UI-SREF活性=活性UI-SREF =wizard.where @>&下;跨度大于1&下; /跨度>其中,< / A>
      &下;一个UI-SREF活性=活性UI-SREF =wizard.what @>&下;跨度大于2&下; /跨度>什么< / A>
      &下;一个UI-SREF活性=活性UI-SREF =wizard.when @>&下;跨度→3&下; /跨度>当< / A>
    < / DIV>
  < /头>  <! - 使用NG-提交赶上表单提交和使用我们的角功能 - >
  <表ID =注册表单NG提交=processForm()>    <! - 我们的嵌套状态的观点将在这里注入 - >
    < D​​IV ID =形式的视图用户界面视图=wizard.where @>< / DIV>
  < /表及GT;
< / DIV>

wizard.where.tpl.html

 < D​​IV CLASS =表单组>
  <标签类=H2为=,其中化合物其中是你的婚礼<?/标签>
  < p n =供应商,其中描述>如果留为空白,在所有可用的位置厂商将会显示< / P>
  < D​​IV CLASS =输入组LG>
    <输入ID =,其中NG-模式=formData.where级=表格控型=文本占位符=波士顿ARIA-describedby的=供应商,其中描述/>
  < / DIV>
< / DIV>< UL类=名单内联>
  <立GT;
    <一个UI的SREF =wizard.what @级=BTN BTN-块BTN-小学>
      下一页<跨度类=发发右箭头>< / SPAN>
    &所述; / A>
  < /李>
< / UL>


解决方案

我创建在这里工作plunker

注:你应该阅读有关国家筑巢和命名视图等等。因为目前的状态和视图定义是完全错误的。

首先,我们不应该有许多的 的意见使用 ONE 状态定义:{} 。但是,我们应该将它们分割成真正的状态。层次结构将有三级

第一级 - 超级根州

  .STATE('家',{
  网址:'/家,
  观点:{
    主:{
      控制器:'HomeCtrl',
      templateUrl:家/ home.tpl.html
    },
  }
})

第二级 - 威泽德,检查,现在我们更改URL。我们会从我们的父母继承它的第一部分(家)

  .STATE(向导,{
  家长:'家',
  // URL:/家/巫师,
  网址:'/巫师,
  控制器:'VendorsCtrl',
  templateUrl:供应商/ wizard.tpl.html
})

第三个层次 - 所有的地方,什么,什么时候目前也将继承网址。它们不必限定父母,因为这是他们的名称的一部分

  .STATE(wizard.where,{
      // URL:/家/精灵/在哪里,
      网址:'/其中',
      控制器:'VendorsCtrl',
      templateUrl:供应商/精灵where.tpl.html',
      //父:向导
})
.STATE(wizard.what,{
      // URL:/家/精灵/什么,
      网址:'/什么,
      控制器:'VendorsCtrl',
      templateUrl:供应商/精灵what.tpl.html',
      //父:向导
})
.STATE(wizard.when,{
      // URL:/家/精灵/时',
      网址:'/时',
      控制器:'VendorsCtrl',
      templateUrl:供应商/精灵when.tpl.html',
      //父:向导
})

威泽德现在必须包含未命名视图目标的 用户界面视图=

 <格UI视图=>< / DIV>

当前的 wizard.tpl.html 包含此:

 <! - 我们的嵌套状态的观点将在这里注入 - >
< D​​IV ID =形式的视图用户界面视图=wizard.where @>< / DIV>

符号 @ 应避免,因为它可以用于absulte视图命名 - 但国家确定指标内。那么,有什么能工作的 用户界面视图=someName

 <! - 我们的嵌套状态的观点将在这里注入 - >
< D​​IV ID =形式的视图用户界面视图=someName>< / DIV>

现在,这些都是(例如这里)视图中的内容 home.tpl

 < D​​IV>
  < H1> HOME< / H1>  <格UI视图=>< / DIV>
< / DIV>

wizzard.tpl

 < D​​IV>
  < H2>&WIZZARD LT; / H>  <格UI视图=>< / DIV>
< / DIV>

因此​​,我们有主屏幕向导国家内部不愿透露姓名的视图目标,这是非常方便的,因为我们可以利用光状态的定义,而不 的意见:{} 对象。这始终是preferred的情况下,我们没有多的看法。

这意味着,这种状态定义将适当地注入到上面的模板:

  //无意见 - 在父母寻找一个用户界面视图=
...
.STATE(wizard.when,{
      网址:'/时',
      控制器:'VendorsCtrl',
      templateUrl:供应商/精灵when.tpl.html',
})
...

检查DOC:

View名称 - 相对与绝对名称


  

在幕后,每一个观点被分配遵循的方案绝对名称 视图名@ Statename的 ,其中视图名是所使用的名称view指令和国家名称是国家的绝对名称,例如: contact.item。您也可以选择在绝对语法来写你的视图名称。


  
  

例如,在previous例如也可以写为:


  .STATE('报告',{
    观点:{
      过滤器@:{},
      资料表@:{},
      图@:{}
    }
})


  

注意该视图名称现在指定为绝对名称,而不是相对的名称。它瞄准的是过滤器,资料表和图形的意见位于根未命名模板。由于它是无名的,没有什么遵循'@'。根不愿透露姓名的模板是您的index.html。


从调用状态的状态

磨片,我们希望在导航状态时,我们可以使用directiv UI-SREF ,但它必须包含国家名称,无法查看命名约定

  //而不是这个
<一个UI的SREF =wizard.what @
我们需要这个
<一个UI的SREF =wizard.what

究其原因,在这个三级分层我们只用父母和孩子的名字的(未盛大父'家')的,是隐藏在状态定义。因为我们用这个:

  .STATE(向导,{
  家长:'家',

家长只是父母,不是国家名称的一部分。这是在这样的情况下良好的(我们需要根/盛大母公司建立一些COMON东西,但它并不需要子状态的名字)

检查DOC:

UI的SREF


  

这是一个结合链路A指令(< A> 标签)来的状态。如果国家有一个相关的URL,该指令将自动生成和放大器;通过更新的 $ state.href()方式href属性。点击链接会触发使用可选参数的状态过渡。结果
  ...


  
  

您可以指定选项传递为 $ state.go()使用 UI-SREF-OPTS 属性。选项​​只限于位置,继承,并重新载入。


  
  

UI-SREF - 字符串 - Statename的可以是任何有效的绝对或相对的状态。


Building a multi-step form ("wizard"). Was originally following this tutorial, which worked great, but am now trying to adapt it so step one is embedded on the homepage rather than being a separate state. No matter what I try, I can not create a ui-sref path that will work. I always get:

Could not resolve '.where' from state 'home'

or

Could not resolve 'wizard.where' from state 'home'

or

Could not resolve 'wizard.where@' from state 'home'

…even though wizard.where@ works fine in <div ui-view="wizard.where@"></div>. What is the correct syntax?

Here are the relevant files:

home.js (left comments intact so you can see various methods I’m trying):

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:

<div class="jumbotron vendate-wizard" ng-controller="VendorsCtrl as vendorsCtrl">
  <header class="page-title">
    <h1>{{ pageTitle }}</h1>
    <p>Answer the following three questions to search available vendors. All answers can be changed later.</p>

    <!-- the links to our nested states using relative paths -->
    <!-- add the active class if the state matches our ui-sref -->
    <div id="status-buttons" class="text-center">
      <a ui-sref-active="active" ui-sref="wizard.where@"><span>1</span> Where</a>
      <a ui-sref-active="active" ui-sref="wizard.what@"><span>2</span> What</a>
      <a ui-sref-active="active" ui-sref="wizard.when@"><span>3</span> When</a>
    </div>
  </header>

  <!-- use ng-submit to catch the form submission and use our Angular function -->
  <form id="signup-form" ng-submit="processForm()">

    <!-- our nested state views will be injected here -->
    <div id="form-views" ui-view="wizard.where@"></div>
  </form>
</div>

wizard.where.tpl.html:

<div class="form-group">
  <label class="h2" for="where">Where Is Your Wedding?</label>
  <p id="vendor-where-description">If left blank, vendors in all available locations will be shown.</p>
  <div class="input-group-lg">
    <input id="where" ng-model="formData.where" class="form-control" type="text" placeholder="Boston, MA" aria-describedby="vendor-where-description" />
  </div>
</div>

<ul class="list-inline">
  <li>
    <a ui-sref="wizard.what@" class="btn btn-block btn-primary">
      Next <span class="fa fa-arrow-right"></span>
    </a>
  </li>
</ul>

解决方案

I created working plunker here

NOTE: You should read about state nesting and named views more. Because the current state and view definition is simply wrong.

Firstly, we should not use the ONE state definition with many views: {}. But we should split them into real states. Hierarchy will have three levels

The first level - super root state

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

The second level - wizzard, check that now we change the url. We will inherit its first part from our parent (home)

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

The third level - all where, what, when now will also inherit url. They do not have to define parent, because it is part of their names

.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
})

Parent wizzard must now contain unnamed view target ui-view=""

<div ui-view=""></div>

Current wizard.tpl.html contains this:

<!-- our nested state views will be injected here -->
<div id="form-views" ui-view="wizard.where@"></div>

The sign @ should be avoided, because it could be used for absulte view naming - BUT inside of the state defintion. So, what could work is ui-view="someName

<!-- our nested state views will be injected here -->
<div id="form-views" ui-view="someName"></div>

Now, these are (in example here) view content of the home.tpl

<div>
  <h1>HOME</h1>

  <div ui-view=""></div>
</div>

And wizzard.tpl

<div>
  <h2>WIZZARD</h2>

  <div ui-view=""></div>
</div>

So, we have unnamed view target inside of home and wizard states, That is very handy, because we can use the light state definition, without views : {} object. And that is always preferred in case we do not have multi-views.

That means, that this state definition will properly be injected into above template:

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

Check the doc:

View Names - Relative vs. Absolute Names

Behind the scenes, every view gets assigned an absolute name that follows a scheme of viewname@statename, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.

For example, the previous example could also be written as:

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

Notice that the view names are now specified as absolute names, as opposed to the relative name. It is targeting the 'filters', 'tabledata', and 'graph' views located in the root unnamed template. Since it's unnamed, there is nothing following the '@'. The root unnamed template is your index.html.

Calling the state from state

Whe we want in where state navigate to when, we can use directiv ui-sref, but it must contain state name, not view naming convention

// instead of this
<a ui-sref="wizard.what@"
we need this
<a ui-sref="wizard.what"

The reason, that in this three level hierarchy we do use only parent and child names (not grand parent 'home'), is hidden in state definition. Because we used this:

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

Parent is just a parent, not part of the state name. Which is good in scenarios like this (we need the root/grand parent to establish some comon stuff, but it name is not needed for substates)

Check the doc:

ui-sref

A directive that binds a link (<a> tag) to a state. If the state has an associated URL, the directive will automatically generate & update the href attribute via the $state.href() method. Clicking the link will trigger a state transition with optional parameters.
...

You can specify options to pass to $state.go() using the ui-sref-opts attribute. Options are restricted to location, inherit, and reload.

ui-sref - string - 'stateName' can be any valid absolute or relative state

这篇关于角UI路由器:嵌套视图不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆