你可以在不重新加载AngularJS控制器的情况下改变路径吗?

Cod*_*er1 185 angularjs

以前有人问过,从答案看起来并不好看.我想考虑一下这个示例代码......

我的应用程序加载提供它的服务中的当前项.有几个控制器可以在不重新加载项目的情况下操纵项目数据.

如果尚未设置,我的控制器将重新加载项目,否则,它将使用服务器之间,控制器之间当前加载的项目.

问题:我想为每个控制器使用不同的路径而不重新加载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'});
    }]);
Run Code Online (Sandbox Code Playgroud)

Item.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>
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

解析度.

状态:使用已接受答案中建议的搜索查询,允许我提供不同的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'});
    }]);
Run Code Online (Sandbox Code Playgroud)

Item.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>
Run Code Online (Sandbox Code Playgroud)

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];
}
Run Code Online (Sandbox Code Playgroud)

directives.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');
      }
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

我的部分内容包含在内 ng-controller=...

And*_*ahl 112

如果你没有使用像的URL #/item/{{item.id}}/foo#/item/{{item.id}}/bar#/item/{{item.id}}/?foo#/item/{{item.id}}/?bar,而不是,你可以设置你的路由/item/{{item.id}}/已经reloadOnSearch设置为false(docs.angularjs.org/api/ngRoute.$routeProvider).这告诉AngularJS如果网址的搜索部分发生更改,则不会重新加载视图.


Vig*_*ond 91

如果您需要更改路径,请在您的app文件中的.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]);
    };
}])
Run Code Online (Sandbox Code Playgroud)

积分转到https://www.consolelog.io/angularjs-change-path-without-reloading,找到我发现的最优雅的解决方案.

  • 好的解决方案 反正有没有让浏览器的后退按钮"尊重"这个? (6认同)
  • 请注意,此解决方案保留旧路由,如果您要求$ route.current,您将获得上一个路径,而不是当前路径.否则这是一个很棒的小黑客. (6认同)
  • 只是想说原始解决方案是由"EvanWinstanley"在这里实际发布的:https://github.com/angular/angular.js/issues/1699#issuecomment-34841248 (4认同)
  • 我一直在使用这个解决方案,并且注意到在某些路径更改时,即使传入了真值,也会将寄存器重新加载为false.还有其他人有这样的问题吗? (2认同)
  • 我必须在return语句之前添加`$ timeout(un,200);`因为有时`$ locationChangeSuccess`在`apply`之后根本没有触发(并且在真正需要时没有改变路由).我的解决方案在调用path(...,false)后清除了一些东西 (2认同)

win*_*mao 17

为什么不把ng-controller放一级呢,

<body ng-controller="ProjectController">
    <div ng-view><div>
Run Code Online (Sandbox Code Playgroud)

并且不要在路线中设置控制器,

.when('/', { templateUrl: "abc.html" })
Run Code Online (Sandbox Code Playgroud)

这个对我有用.

  • 这是一个伟大的"俄罗斯人使用铅笔"的答案,适合我:) (4认同)

Dan*_*hka 12

对于那些需要路径()更改而没有控制器重新加载的人 - 这是插件:https://github.com/anglibs/angular-location-update

用法:

$location.update_path('/notes/1');
Run Code Online (Sandbox Code Playgroud)

基于/sf/answers/1687149761/

PS此解决方案/sf/answers/1687149761/包含调用path(,false)之后的错误 - 它将向后/向前打破浏览器导航,直到调用path(,true)


Luk*_*kus 10

虽然这篇文章很老并且已经接受了答案,但使用reloadOnSeach = false并不能解决我们这些需要改变实际路径而不仅仅是params的问题.这是一个需要考虑的简单解决方案:

使用ng-include而不是ng-view并在模板中分配控制器.

<!-- In your index.html - instead of using ng-view -->
<div ng-include="templateUrl"></div>

<!-- In your template specified by app.config -->
<div ng-controller="MyController">{{variableInMyController}}</div>

//in config
$routeProvider
  .when('/my/page/route/:id', { 
    templateUrl: 'myPage.html', 
  })

//in top level controller with $route injected
$scope.templateUrl = ''

$scope.$on('$routeChangeSuccess',function(){
  $scope.templateUrl = $route.current.templateUrl;
})

//in controller that doesn't reload
$scope.$on('$routeChangeSuccess',function(){
  //update your scope based on new $routeParams
})
Run Code Online (Sandbox Code Playgroud)

唯一不足的是你不能使用resolve属性,但这很容易解决.此外,您必须管理控制器的状态,例如基于$ routeParams的逻辑,因为随着相应的URL更改,路径在控制器内发生更改.

这是一个例子:http://plnkr.co/edit/WtAOm59CFcjafMmxBVOP?p = preview