根据路由切换 ng-include 的可见性
Posted
技术标签:
【中文标题】根据路由切换 ng-include 的可见性【英文标题】:Toggle visibility of a ng-include depending on route 【发布时间】:2013-02-14 02:32:45 【问题描述】:我有以下配置:
$routeProvider
.when('/cars', templateUrl: 'app/cars/index.html', controller: 'CarsCtrl', reloadOnSearch: false )
.when('/bikes', templateUrl: 'app/bikes/index.html', controller: 'BikesCtrl', reloadOnSearch: false );
在我的根 index.html 的某处有一个:
<a href="#/cars">Cars</a>
<a href="#/bikes">Bikes</a>
<div ng-view></div>
现在,我希望两个视图同时在 DOM 中加载和生成,并根据路由/URL 显示其中一个。
类似于以下内容(不是实际的工作代码,只是为了给您一个想法)。
app.js:
$routeProvider
.when('/cars', controller: 'CarsCtrl', reloadOnSearch: false )
.when('/bikes', controller: 'BikesCtrl', reloadOnSearch: false );
根索引.html:
<a href="#/cars">Cars</a>
<a href="#/bikes">Bikes</a>
<div ng-include="'app/cars/index.html'" ng-show="carsVisible"></div>
<div ng-include="'app/bikes/index.html'" ng-show="bikesVisible"></div>
更新:我知道 ng-view 可以做到这一点,但差异是存在的,如果很微妙的话。我希望每个视图的 html 生成一次并始终保留在 DOM 中。
【问题讨论】:
使用 ng-view 无法做到这一点。但问题是,你为什么真的要这样做。是因为您想“预处理”每条路线以使其加载更快吗?路由已经相当快了,除非你的控制器需要一些异步数据,在这种情况下你会在路由定义对象中使用'resolve',再加上一些用于在后台获取异步数据的应用程序初始化代码。 【参考方案1】:我找到了另一种方式,我认为是最简单、最快、最容易管理的:
How to set bootstrap navbar active class with Angular JS?
这是:
使用 ng-controller 在 ng-view 之外运行单个控制器:
<div class="collapse navbar-collapse" ng-controller="HeaderController">
<ul class="nav navbar-nav">
<li ng-class=" active: isActive('/')"><a href="/">Home</a></li>
<li ng-class=" active: isActive('/dogs')"><a href="/dogs">Dogs</a></li>
<li ng-class=" active: isActive('/cats')"><a href="/cats">Cats</a></li>
</ul>
</div>
<div ng-view></div>
并包含在 controllers.js 中:
function HeaderController($scope, $location)
$scope.isActive = function (viewLocation)
return viewLocation === $location.path();
;
【讨论】:
【参考方案2】:使用带有 show 指令的服务:
<div ng-show="myService.isActive('/')">Show this when at default route</div>
<div ng-show="myService.isActive('/cars')">Show this when at cars</div>
服务:
myApp.factory('MyService',
function ($location)
return
isActive: function (path)
return (($location.path() == path));
);
App.js:
// this is run after angular is instantiated and bootstrapped
myApp.run(function ($rootScope, myService)
$rootScope.breadcrumbService = MyService;
);
【讨论】:
【参考方案3】:我创建了一个 RouteCtrl 来通过 ng-include 加载您的所有视图。不使用 ng-view。我内联了模板。模板可以包含它们自己的 ng-controller 指令来拉入特定的控制器。
<body ng-controller="RouteCtrl">
<a href="#/cars">Cars</a>
<a href="#/bikes">Bikes</a>
<div ng-controller="RouteCtrl">
<div ng-include="'/cars.html'" ng-show="carsVisible"></div>
<div ng-include="'/bikes.html'" ng-show="bikesVisible"></div>
</div>
<script type="text/ng-template" id="/cars.html">
Cars template.
</script>
<script type="text/ng-template" id="/bikes.html">
Bikes template.
</script>
$routeProvider 仍然配置,但没有指定模板或控制器,导致 RouteCtrl 始终处于活动状态。该控制器监听 $routeChangeSuccess
事件并相应地操作 ng-show 属性。
app.config(function($routeProvider)
$routeProvider
.when('/cars', )
.when('/bikes', )
);
app.controller('RouteCtrl', function($scope, $route, $location)
$scope.$on('$routeChangeSuccess', function()
var path = $location.path();
console.log(path);
$scope.carsVisible = false;
$scope.bikesVisible = false;
if(path === '/cars')
$scope.carsVisible = true;
else if(path === '/bikes')
$scope.bikesVisible = true;
);
);
Plunker
这个解决方案的想法来自@Andy。
【讨论】:
【参考方案4】:您应该使用ng-view
,而不是使用ng-include
;
这将显示app/cars/index.html
或app/bikes/index.html
的内容
<a href="#/cars">Cars</a>
<a href="#/bikes">Bikes</a>
<div ng-view></div>
查看http://docs.angularjs.org/tutorial/step_07的模板部分
【讨论】:
嗨帕斯卡,感谢您的回复!然而,这不是我要找的。我在我的问题中做了澄清。 ng-view 将切换内容,是的,但它通过在每次路由更改时从现有视图中删除内容并插入新视图的内容来实现。我希望这两个内容都已经呈现,并且只需使用 ng-show 或 CSS 显示切换一个或另一个。 您在哪里/何时更改carsVisible
和bikesVisible
,您在根index.html
的某处有控制器吗?以上是关于根据路由切换 ng-include 的可见性的主要内容,如果未能解决你的问题,请参考以下文章