3

複数のタブに分散された HTML フォーム要素を含むページがあります。ユーザーがフォーム要素に入力したデータを失うことなくタブを切り替えられるようにしたい (また、不必要なデータのリロードを節約したい)。そして、特定のタブへのリンクを誰かに渡すことができるようにしたいと考えています。

ui-extras のスティッキー状態は、私が必要としているものを正確に実行する必要があるようです。私がそれを機能させるのに非常に失敗したことを除いて。

サンプルのソース コードを調べて、サンプルを起動すると、たとえば、controllers.js の 57 行目にある在庫コントローラーのコンストラクターに firebug でブレークポイントを設定すると、コンストラクターが 1 回だけ起動されることがわかります。ただし、コントローラー コンストラクターは何度も起動され、スティッキー状態が存在しない場合とほとんど同じようにアプリケーションが動作しますが、スティッキー状態のデバッグを有効にすると、何かを実行していることがわかります (状態の非アクティブ化と再アクティブ化)。

この回答のコメントで、スティッキー状態は名前付きビューでのみ機能すると述べている人を見つけたので、ビューに名前を付けようとしましたが、違いはありませんでした。

タブの前に明示的な「ルート状態」を挿入してみました。

ng-controller または状態のコントローラー定義によって、コントローラーを挿入しようとしました。

github の例は素晴らしい見せびらかしですが、最小限以上のものであり、実際に何が必要で何が必要でないかを理解するのが難しくなっています。

スティッキー ステートを使い始めるために必要な最小限の例は何ですか? (ボーナス: 私のコードの何が問題なのですか?)。

参考までに、失敗した試行の plunkr をここに示します(以前の試行の選択を確認するには、履歴を参照してください)。

これが私の現在の失敗したソースコードです:

var log = '';

function mkController(msg) {
  return function($scope) {
    // This is the constructor of a controller
    // I'd expect this constructor to the first time a state is loaded.
    // When switching to a sister state and back it should not be called again.

    if (!$scope.random) {
      // I expect the $scope object to be retained when changing states for and
      // back. So even if my assumption that the controller will be persistent
      // would be wrong this is to check whether the $scope survives.
      // If the scope survives the random number will be initialized only once
      // and then it won't change anymore:

      $scope.random = Math.round(Math.random()*10000);
    }
    // This log will tell us how often the controller constructor has been called
    // (Should be only once, I think)
    log += 'creating: ' + msg + '\n';
    this.message = log;
  }
}
angular.module('plunker', ['ui.router', 'ct.ui.router.extras.sticky', 'ct.ui.router.extras.dsr'])
.controller('ControllerA', mkController('ControllerA'))
.controller('ControllerB', mkController('ControllerB'))
.run(function($templateCache) {
  $templateCache.put('root.html', '<div ui-view="myview"></div>');
  $templateCache.put('templateA.html', '<div ng-controller="ControllerA as controller"><pre>Random: {{random}}, Message (templateA): {{controller.message}}</pre></div>');
  $templateCache.put('templateB.html', '<div ng-controller="ControllerB as controller"><pre>Random: {{random}}, Message (templateB): {{controller.message}}</pre></div>');
})
.config(function($stateProvider) {
  $stateProvider
  .state('root', {
    url: '/',
    templateUrl: 'root.html'
  }).state('root.stateA', {
    url: '/stateA',
    views: {
      myview: {
        templateUrl: 'templateA.html',
      }
    },
    sticky: true,
    deepStateRedirect: true
  }).state('root.stateB', {
    url: '/stateB',
    views: {
      myview: {
        templateUrl: 'templateB.html',
      }
    },
    sticky: true,
    deepStateRedirect: true
  });
})
.config(function($stickyStateProvider) {
  $stickyStateProvider.enableDebug(true);
});
4

1 に答える 1

8

私はそれを考え出した:

  • まず第一に、名前付きビューが実際にどのように使用されることを意図しているのか、つまり、タブごとに個別のビューを使用することを理解していませんでした。
  • 次に、自分でビューを非表示にして表示する必要があることに気づきませんでした。

どちらもデモ ページで言及されていますが、これはこの特定のデモに関する単なる情報だと思っていたため、デモ ページのテキストを詳しく読んでいないことを認めなければなりません。

とにかく:スティッキー状態を実現するために最低限必要だと私が信じている例を次に示します。

HTML

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link href="style.css" rel="stylesheet" />
    <script data-semver="1.3.12" src="https://code.angularjs.org/1.3.12/angular.js" data-require="angular.js@1.3.x"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.13/angular-ui-router.js"></script>
    <script src="ui-router-extras.js"></script>
    <script src="app.js"></script>
  </head>

  <body>
    <ul class="nav nav-tabs nav-tabs-head" role="tablist">
        <li ui-sref-active="active"><a ui-sref="root.stateA" role="tab">StateA</a></li>
        <li ui-sref-active="active"><a ui-sref="root.stateB" role="tab">StateB</a></li>
    </ul>
    <div ui-view="" />
  </body>

</html>

JavaScript

var log = '';

function mkController(msg) {
  return function($scope) {
    // This is the constructor of a controller
    // I'd expect this constructor to the first time a state is loaded.
    // When switching to a sister state and back it should not be called again.

    if (!$scope.random) {
      // I expect the $scope object to be retained when changing states for and
      // back. So even if my assumption that the controller will be persistent
      // would be wrong this is to check whether the $scope survives.
      // If the scope survives the random number will be initialized only once
      // and then it won't change anymore:

      $scope.random = Math.round(Math.random()*10000);
    }
    // This log will tell us how often the controller constructor has been called
    // (Should be only once, I think)
    log += 'creating: ' + msg + '\n';
    this.message = 'Current msg: ' + msg + '\n\n' + log;
  }
}
angular.module('plunker', ['ui.router', 'ct.ui.router.extras.sticky'])
.controller('ControllerA', mkController('ControllerA'))
.controller('ControllerB', mkController('ControllerB'))
.config(function($stateProvider) {
  $stateProvider
  .state('root', {
    url: '/',
    template: '<div ui-view="a" ng-show="$state.includes(\'root.stateA\')"></div><div ui-view="b"  ng-show="$state.includes(\'root.stateB\')"></div>'
  }).state('root.stateA', {
    url: '/stateA',
    views: {
      'a@root': {
        template: '<div ng-controller="ControllerA as controller"><h1>A</h1><pre>Random: {{random}}, Message (templateA): {{controller.message}}</pre></div>',
      }
    },
    sticky: true
  }).state('root.stateB', {
    url: '/stateB',
    views: {
      'b@root': {
        template: '<div ng-controller="ControllerB as controller"><h1>B</h1><pre>Random: {{random}}, Message (templateB): {{controller.message}}</pre></div>',
      }
    },
    sticky: true
  });
})
.config(function($stickyStateProvider) {
  $stickyStateProvider.enableDebug(true);
})
.run(function ($rootScope, $state) {
  $rootScope.$state = $state;
});

plunkr でのデモ

リンク

于 2015-02-05T12:48:36.827 に答える