一尘不染

Angular-UI路由器:嵌套视图不起作用

angularjs

建立一个多步骤表单(“向导”)。最初是按照本教程进行的该教程效果很好,但是现在尝试对其进行调整,因此第一步已嵌入首页中,而不是单独的状态。无论我做什么,我都无法创建一条ui- sref可行的路径。我总是得到:

无法从状态“ home”解析“ .where”

要么

无法从状态“家”解析“ wizard.where”

要么

无法从状态“ home”解析“ wizard.where @”

…即使在中wizard.where@效果很好<div ui-view="wizard.where@"></div>。正确的语法是什么?

以下是相关文件:

home.js (完整保留左侧注释,以便您可以看到我正在尝试的各种方法):

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>

阅读 222

收藏
2020-07-04

共1个答案

一尘不染

我在这里创建了工作插件

注意:您应该阅读有关状态嵌套和命名视图的更多信息。 因为当前状态和视图定义完全错误。

首先,我们不应将 ONE 状态定义与many一起使用 views: {} 。但是我们应该将它们分为真实状态。层次结构将
分为三个层次

第一级-超级根状态

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

第二级-向导,检查是否现在我们更改了URL。我们将从父母(家)那里继承第一部分

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

第三层-所有位置,位置,时间以及现在都将继承url。他们不必定义父级,因为它是其名称的一部分

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

父级 向导 现在必须包含未命名的视图目标 ui-view=""

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

当前的 Wizard.tpl.html 包含以下内容:

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

@ 应该避免使用该符号,因为它可以用于绝对视图命名-状态定义内的BUT。所以,可行的是 ui-view="someName

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

现在,这些是(在此处的示例中)视图内容
home.tpl

<div>
  <h1>HOME</h1>

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

wizzard.tpl

<div>
  <h2>WIZZARD</h2>

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

因此,我们在 home 状态和 向导 状态内部具有未命名的视图目标,这非常方便,因为我们可以使用轻状态定义而无需 views : {} 对象。如果我们没有多视图,那总是首选。

这意味着该状态定义将被正确地注入上述模板中:

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

检查文档:

[视图名称-相对名称与绝对名称](https://github.com/angular-ui/ui-router/wiki/Multiple-

Named-Views#view-names—relative-vs-absolute-names)

在幕后,每个视图都被分配一个遵循方案的绝对名称 viewname@statename
,其中viewname是view指令中使用的名称,状态名称是该状态的绝对名称,例如contact.item。您还可以选择以绝对语法编写视图名称。

例如,前面的示例也可以写成:

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

请注意,现在将视图名称指定为绝对名称,而不是相对名称。它的目标是位于未命名的根模板中的“过滤器”,“表数据”和“图形”视图。由于未命名,因此@后面没有任何内容。未命名的根模板是您的index.html。

从状态调用状态

我们想要在状态导航到何时的位置,可以使用Directiv ui-sref,但它必须包含状态名称,而不是视图命名约定

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

原因是,在此三级层次结构中,我们仅使用父级和子级名称 (而不是父级“ home”) ,因此隐藏在状态定义中。因为我们使用了这个:

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

父母只是父母,而不是州名的一部分。在这种情况下这很好 (我们需要root / grand父级来建立一些通用的东西,但是子状态不需要它的名称)

检查文档:

ui-sref

将链接(<a>标记)绑定到状态的指令。如果状态具有关联的URL,则该伪指令将通过 $ state.href()
方法自动生成并更新href属性。单击链接将触发带有可选参数的状态转换。

您可以使用属性指定要传递给 $ state.go()的 选项ui-sref-opts。选项仅限于位置,继承和重新加载。

ui-sref -字符串 -‘stateName’ 可以是任何有效的绝对或相对状态

2020-07-04