13

Angularアプリにモーダルウィンドウ(基本的には、コンパイルされたテンプレートとともに読み込まれる非表示のdiv)を表示する必要があります。問題は、モーダルが開いたときにURLを変更して、ユーザーがリンクをコピーしてモーダルウィンドウに直接移動し、戻るボタンを使用してモーダルウィンドウを閉じて前のページに戻ることができるようにする必要があることです。これは、ピンをクリックしたときにPinterestがモーダルウィンドウを処理する方法に似ています。

これまで、テンプレートをロードし、$ compileを使用してコンパイルし、$ scopeを挿入して、コンパイルされたテンプレートを表示するディレクティブを作成しました。これは正常に機能します。

問題は、$ locationを使用してパスを変更するとすぐに、ルートコントローラーが起動し、テンプレートがng-viewに読み込まれることです。

これを克服する2つの方法を考えましたが、どちらも実装できませんでした。

  1. $ locationを使用してURLを変更したときに、どういうわけかルートコントローラーが起動しないようにします。デフォルトが発生しないように$routeChangeStartにリスナーを追加しましたが、それは機能していないようです。

  2. どういうわけか、ページに別のビューハンドラーを追加し(基本的に、ページに2つの名前付きng-viewディレクティブがあります)、それぞれが異なるルートを処理できるようにします。ただし、現時点ではAngularがこれをサポートしていることはわかりません。

URLは、/ item?item_id = 12345ではなく、/ item/item_idの形式である必要があります。

どんな助けでもいただければ幸いです。

4

5 に答える 5

13

ここで説明されているように ui.router モジュールを使用すると、これを行うことができます: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-open-a-dialogmodal -特定の状態で。

彼らの例:

$stateProvider.state("items.add", {
    url: "/add",
    onEnter: function($stateParams, $state, $modal, $resource) {
        $modal.open({
            templateUrl: "items/add",
            resolve: {
              item: function() { new Item(123).get(); }
            },
            controller: ['$scope', 'item', function($scope, item) {
                $scope.dismiss = function() {
                    $scope.$dismiss();
                };

                $scope.save = function() {
                    item.update().then(function() {
                        $scope.$close(true);
                    });
                };
            }]
        }).result.then(function(result) {
            if (result) {
                return $state.transitionTo("items");
            }
        });
    }
});

また、「errorCallback」関数を then() 関数に渡して、Escape キーを押すか背景をクリックしてモーダル解除を処理します。

于 2014-01-19T05:05:58.910 に答える
7

同様の要件がありました。必要だった:

  • ルートへの変更をトリガーするモーダル ウィンドウ。独自のハッシュ URL があります。
  • モーダル URL にアクセスすると、メイン画面が読み込まれ、モーダルが popop にトリガーされます。
  • 戻るボタンはモーダルを閉じます (ホーム画面から開始したと仮定します)。
  • [OK] または [キャンセル] をクリックすると、モーダルが閉じられ、ルートがホーム画面に戻ります。
  • 背景をクリックしてモーダルを閉じると、ルートがホーム画面に戻ります。

これらすべてが連携して動作する良い例は見つかりませんでしたが、断片的な例を見つけることができたので、次のようにそれらをすべてまとめて動作例にしました。

<!DOCTYPE html>
<html lang="en" ng-app="app">

<head>
  <meta charset="UTF-8">
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.11/angular-ui-router.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.2/ui-bootstrap-tpls.js"></script>
  <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/css/bootstrap.css" rel="stylesheet">
  <script>

    // init the app with ui.router and ui.bootstrap modules
    var app = angular.module('app', ['ui.router', 'ui.bootstrap']);

    // make back button handle closing the modal
    app.run(['$rootScope', '$modalStack',
      function($rootScope, $modalStack) {
        $rootScope.$on('$stateChangeStart', function() {
          var top = $modalStack.getTop();
          if (top) {
            $modalStack.dismiss(top.key);
          }
        });
      }
    ]);

    // configure the stateProvider
    app.config(['$stateProvider', '$urlRouterProvider',
      function($stateProvider, $urlRouterProvider) {

        // default page to be "/" (home)
        $urlRouterProvider.otherwise('/');

        // configure the route states
        $stateProvider

          // define home route "/"
          .state('home', {
            url: '/'
          })

          // define modal route "/modal"
          .state('modal', {
            url: '/modal',

            // trigger the modal to open when this route is active
            onEnter: ['$stateParams', '$state', '$modal',
              function($stateParams, $state, $modal) {
                $modal

                  // handle modal open
                  .open({
                    template: '<div class="modal-header"><h3 class="modal-title">Modal</h3></div><div class="modal-body">The modal body...</div><div class="modal-footer"><button class="btn btn-primary" ng-click="ok()">OK</button><button class="btn btn-warning" ng-click="cancel()">Cancel</button></div>',
                    controller: ['$scope',
                      function($scope) {
                        // handle after clicking Cancel button
                        $scope.cancel = function() {
                          $scope.$dismiss();
                        };
                        // close modal after clicking OK button
                        $scope.ok = function() {
                          $scope.$close(true);
                        };
                      }
                    ]
                  })

                  // change route after modal result
                  .result.then(function() {
                    // change route after clicking OK button
                    $state.transitionTo('home');
                  }, function() {
                    // change route after clicking Cancel button or clicking background
                    $state.transitionTo('home');
                  });

              }
            ]

          });
      }
    ]);
  </script>
</head>

<body>

  <a href="#/modal" class="btn btn-default">POPUP!</a>

  <div ui-view></div>

</body>

</html>

plunkr.co/edit/tLyfRP6sx9C9Vee7pOfC: plunkr.co/edit/tLyfRP6sx9C9Vee7pOfC

plunker の [埋め込みビューを開く] リンクをクリックして、ハッシュ タグが機能していることを確認します。

于 2014-12-03T23:01:35.607 に答える
5

hermanschutte のソリューションは機能しました ( Tiago Roldão の投稿のコメントを参照)。明確にするために、段階的に投稿しています。

まず、設定で:

.when('/posts', {
  templateUrl: 'views/main.html',
  controller: 'MainCtrl',
  reloadOnSearch: false     // this allows us to use the back button to get out of modals.
})

次に、モーダルを開くと(場所モジュールが必要になります):

$location.search('modal');

そしてモーダルコントローラーでは:

$scope.$on('$locationChangeSuccess', function() {
  $scope.close(); // call your close function
});
于 2013-08-27T15:30:34.830 に答える
2

AngularJSソースコードを取得し、$routeと$routeProviderの独自の抽出を微調整してロードしてから、それらをAngularネイティブに注入することをお勧めします。

おそらく、ルート変更のトリガーをインターセプトするためにフラグを追加するだけで済みます。

もう1つの簡単なオプションは、渡されたイベントを使用$scope.$on(event_name, function callback(ev) {...})して呼び出すことにより、イベントシステムにフックし.preventDefault()、内部の$routeトリガーを停止することを期待することです。ロケーションシステムはイベントをブロードキャストし、イベントを生成する前に属性を$locationChangeStartチェックします。defaultPrevented$locationChangeSuccess

結果を公開することを忘れないでください!

于 2012-12-11T16:02:33.477 に答える
2

あなたが言及した名前付きビュー ソリューションは、angularJS メーリング リストで大きな議論がありましたが、現在 (および近未来から中期にかけて) $route システムは複数のビューを処理しません。

私がいくつかの場所で述べたように、そしてここでも数回同様に、 $route システムは angular の非常に独断的なスタンスが障害になる可能性がある状況の 1 つです。構成可能。私は個人的には直接使用しませんが、ここで見つけたソリューションを介してバイパスします。

少し複雑になりますが、柔軟性が向上します。$route は (手動の) レンダリング関数をトリガーするためだけに機能し、そこで値を割り当てて、必要に応じて $broadcasts をトリガーできるという考えです (通常、メインからコントローラ)。

私が試していないことの 1 つは、「ハイブリッド」ソリューションです。つまり、$route システムを通常どおり使用し、ビュー パラメータを持たないように /item/item_id ルートを構成します (メイン ビューが変更されないように、 $routeChangeStart イベントを介して何かを行います (参照したページからわかるように、ルートに任意の値を割り当てることができることを思い出してください)

繰り返しますが、個人的には代替方法を完全に使用することを好みます。

于 2012-12-11T10:59:49.337 に答える