195

以前に尋ねられたことがありますが、答えからすると良く見えません。このサンプルコードを参考にお願いしたいのですが…

私のアプリは、それを提供するサービスで現在のアイテムをロードします。アイテムをリロードせずにアイテム データを操作するコントローラーがいくつかあります。

まだ設定されていない場合、コントローラーはアイテムをリロードします。それ以外の場合は、コントローラー間で、サービスから現在読み込まれているアイテムを使用します。

問題: Item.html をリロードせずに、コントローラーごとに異なるパスを使用したいと考えています。

1) それは可能ですか?

2)それが不可能な場合、ここで思いついたものと比較して、コントローラーごとにパスを持つためのより良いアプローチはありますか?

app.js

var app = angular.module('myModule', []).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/items', {templateUrl: 'partials/items.html',   controller: ItemsCtrl}).
      when('/items/:itemId/foo', {templateUrl: 'partials/item.html', controller: ItemFooCtrl}).
      when('/items/:itemId/bar', {templateUrl: 'partials/item.html', controller: ItemBarCtrl}).
      otherwise({redirectTo: '/items'});
    }]);

アイテム.html

<!-- Menu -->
<a id="fooTab" my-active-directive="view.name" href="#/item/{{item.id}}/foo">Foo</a>
<a id="barTab" my-active-directive="view.name" href="#/item/{{item.id}}/bar">Bar</a>
<!-- Content -->
<div class="content" ng-include="" src="view.template"></div>

controller.js

// Helper function to load $scope.item if refresh or directly linked
function itemCtrlInit($scope, $routeParams, MyService) {
  $scope.item = MyService.currentItem;
  if (!$scope.item) {
    MyService.currentItem = MyService.get({itemId: $routeParams.itemId});
    $scope.item = MyService.currentItem;
  }
}
function itemFooCtrl($scope, $routeParams, MyService) {
  $scope.view = {name: 'foo', template: 'partials/itemFoo.html'};
  itemCtrlInit($scope, $routeParams, MyService);
}
function itemBarCtrl($scope, $routeParams, MyService) {
  $scope.view = {name: 'bar', template: 'partials/itemBar.html'};
  itemCtrlInit($scope, $routeParams, MyService);
}

解像度。

ステータス:受け入れられた回答で推奨されているように検索クエリを使用すると、メインコントローラーをリロードせずにさまざまな URL を提供できました。

app.js

var app = angular.module('myModule', []).
  config(['$routeProvider', function($routeProvider) {
    $routeProvider.
      when('/items', {templateUrl: 'partials/items.html',   controller: ItemsCtrl}).
      when('/item/:itemId/', {templateUrl: 'partials/item.html', controller: ItemCtrl, reloadOnSearch: false}).
      otherwise({redirectTo: '/items'});
    }]);

アイテム.html

<!-- Menu -->
<dd id="fooTab" item-tab="view.name" ng-click="view = views.foo;"><a href="#/item/{{item.id}}/?view=foo">Foo</a></dd>
<dd id="barTab" item-tab="view.name" ng-click="view = views.bar;"><a href="#/item/{{item.id}}/?view=foo">Bar</a></dd>

<!-- Content -->
<div class="content" ng-include="" src="view.template"></div>

controller.js

function ItemCtrl($scope, $routeParams, Appts) {
  $scope.views = {
    foo: {name: 'foo', template: 'partials/itemFoo.html'},
    bar: {name: 'bar', template: 'partials/itemBar.html'},
  }
  $scope.view = $scope.views[$routeParams.view];
}

ディレクティブ.js

app.directive('itemTab', function(){
  return function(scope, elem, attrs) {
    scope.$watch(attrs.itemTab, function(val) {
      if (val+'Tab' == attrs.id) {
        elem.addClass('active');
      } else {
        elem.removeClass('active');
      }
    });
  }
});

私のパーシャル内のコンテンツはでラップされていますng-controller=...

4

12 に答える 12

120

#/item/{{item.id}}/fooのようなURLを使用する必要#/item/{{item.id}}/barがない場合は#/item/{{item.id}}/?foo#/item/{{item.id}}/?bar代わりに、に設定するようにルートを設定でき/item/{{item.id}}/ますreloadOnSearchfalsehttps://docs.angularjs.org/api/ngRoute/provider/$routeProvider 。これは、URLの検索部分が変更された場合にビューをリロードしないようにAngularJSに指示します。

于 2013-02-20T07:27:30.997 に答える
94

パスを変更する必要がある場合は、アプリ ファイルの .config の後にこれを追加します。次に$location.path('/sampleurl', false);、リロードを防ぐために行うことができます

app.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
    var original = $location.path;
    $location.path = function (path, reload) {
        if (reload === false) {
            var lastRoute = $route.current;
            var un = $rootScope.$on('$locationChangeSuccess', function () {
                $route.current = lastRoute;
                un();
            });
        }
        return original.apply($location, [path]);
    };
}])

私が見つけた最もエレガントなソリューションについては、https://www.consolelog.io/angularjs-change-path-without-reloadingにクレジットを入れてください。

于 2014-06-08T01:14:36.390 に答える
18

なぜ ng-controller を 1 つ上のレベルに上げないのか、

<body ng-controller="ProjectController">
    <div ng-view><div>

ルートにコントローラーを設定しないでください。

.when('/', { templateUrl: "abc.html" })

わたしにはできる。

于 2014-11-17T23:30:38.280 に答える
2

このソリューションを使用します

angular.module('reload-service.module', [])
.factory('reloadService', function($route,$timeout, $location) {
  return {
     preventReload: function($scope, navigateCallback) {
        var lastRoute = $route.current;

        $scope.$on('$locationChangeSuccess', function() {
           if (lastRoute.$$route.templateUrl === $route.current.$$route.templateUrl) {
              var routeParams = angular.copy($route.current.params);
              $route.current = lastRoute;
              navigateCallback(routeParams);
           }
        });
     }
  };
})

//usage
.controller('noReloadController', function($scope, $routeParams, reloadService) {
     $scope.routeParams = $routeParams;

     reloadService.preventReload($scope, function(newParams) {
        $scope.routeParams = newParams;
     });
});

このアプローチでは戻るボタンの機能が保持され、私が見た他のアプローチとは異なり、テンプレートには常に現在の routeParams があります。

于 2016-04-10T00:17:00.603 に答える
0

@Vigrondと@rahilwazirが見逃したいくつかのことを解決する、より完全なソリューションを次に示します。

  • 検索パラメーターが変更されると、$routeUpdate.
  • ルートが実際に変更されていない場合、$locationChangeSuccessがトリガーされることはなく、次のルート更新が妨げられます。
  • 同じダイジェスト サイクルで別の更新要求があり、今回は再読み込みを希望する場合、イベント ハンドラーはその再読み込みをキャンセルします。

    app.run(['$rootScope', '$route', '$location', '$timeout', function ($rootScope, $route, $location, $timeout) {
        ['url', 'path'].forEach(function (method) {
            var original = $location[method];
            var requestId = 0;
            $location[method] = function (param, reload) {
                // getter
                if (!param) return original.call($location);
    
                # only last call allowed to do things in one digest cycle
                var currentRequestId = ++requestId;
                if (reload === false) {
                    var lastRoute = $route.current;
                    // intercept ONLY the next $locateChangeSuccess
                    var un = $rootScope.$on('$locationChangeSuccess', function () {
                        un();
                        if (requestId !== currentRequestId) return;
    
                        if (!angular.equals($route.current.params, lastRoute.params)) {
                            // this should always be broadcast when params change
                            $rootScope.$broadcast('$routeUpdate');
                        }
                        var current = $route.current;
                        $route.current = lastRoute;
                        // make a route change to the previous route work
                        $timeout(function() {
                            if (requestId !== currentRequestId) return;
                            $route.current = current;
                        });
                    });
                    // if it didn't fire for some reason, don't intercept the next one
                    $timeout(un);
                }
                return original.call($location, param);
            };
        });
    }]);
    
于 2016-09-26T16:03:50.833 に答える
0

次の head タグを追加します

  <script type="text/javascript">
    angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
  </script>

これにより、リロードが防止されます。

于 2017-03-29T02:42:22.517 に答える