web-dev-qa-db-ja.com

Angular-UI Router:ネストされたビューが機能しない

マルチステップフォーム(「ウィザード」)の構築。元々 このチュートリアル に従っていましたが、これはうまく機能しましたが、現在は適応させようとしているので、ステップ1は独立した状態ではなくホームページに埋め込まれています。何を試しても、ui-sref動作するパス。私はいつも得る:

状態「home」から「.where」を解決できませんでした

または

状態「home」から「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>
14
Hugh Guiney

私は作成しました ここで働く配管工

注:状態のネストと名前付きビューについて詳しく読む必要があります。現在の状態とビューの定義が単に間違っているからです。

まず、[〜#〜] one [〜#〜]状態定義を多くのviews: {}と共に使用しないでください。しかし、それらを実際の状態に分割する必要があります。階層はつのレベルになります

最初のレベル-スーパールート状態

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

2番目のレベル-ウィザード、今URLを変更することを確認します。最初の部分を親(ホーム)から継承します

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

3番目のレベル-すべての場所、内容、現在も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
})

wizzardには名前のないビューターゲットを含める必要があります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>

記号@は、絶対的なビューの命名に使用できるため、避ける必要があります-ただし、状態の定義の内部です。したがって、動作するのは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およびwizardステート内に名前のないビューターゲットがあります。これは非常に便利です。ライトステートの定義をviews : {}オブジェクト。また、マルチビューがない場合は常にこれが優先されます。

つまり、この状態定義は上記のテンプレートに適切に挿入されます。

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

ドキュメントを確認してください:

ビュー名-相対名と絶対名

舞台裏では、すべてのビューにviewname@statenameのスキームに従う絶対名が割り当てられます。ここで、viewnameはビューディレクティブで使用される名前であり、状態名は状態の絶対名です。 contact.item。ビュー名を絶対構文で記述することもできます。

たとえば、前の例は次のように書くこともできます。

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

ビュー名は、相対名ではなく絶対名として指定されていることに注意してください。ルートの名前のないテンプレートにある「フィルター」、「テーブルデータ」、および「グラフ」ビューをターゲットにしています。名前がないため、「@」の後には何もありません。ルートの名前のないテンプレートは、index.htmlです。

状態から状態を呼び出す

状態がいつどこにナビゲートするか、directive ui-srefを使用できますが、名前付け規則を表示するのではなく、状態名を含める必要があります

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

この3レベルの階層では、親と子の名前(グランド親 'home')ではなくのみを使用する理由は、状態の定義に隠されています。これを使用したため:

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

親は単なる親であり、州名の一部ではありません。これはこのようなシナリオで良いです(いくつかの共通のものを確立するためにルート/グランド親が必要ですが、サブステートには名前は必要ありません)

ドキュメントを確認してください:

i-sref

リンク(<a>タグ)を状態にバインドするディレクティブ。状態にURLが関連付けられている場合、ディレクティブは$ state.href()メソッドを介してhref属性を自動的に生成および更新します。リンクをクリックすると、オプションのパラメーターで状態遷移がトリガーされます。
...

ui-sref-opts属性を使用して、$ state.go()に渡すオプションを指定できます。オプションは、ロケーション、継承、およびリロードに制限されています。

ui-sref-文字列-'stateName'は、有効な絶対状態または相対状態にすることができます

42
Radim Köhler

[S] tep oneは、独立した状態ではなく、ホームページに埋め込まれています

各ui-viewを状態として扱う必要がありますが、wizard.whereとして デフォルト/インデックス状態

チュートリアルでは$ urlRouterProviderを使用してform/profileデフォルト状態。

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

ただし、この方法では、/form/form/profile

ただし、 マイナー修正 を使用して空のURL状態を作成できます。

// 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は、UIルーターと状態の定義に関する優れた洞察も提供しています。

3
SirTophamHatt