最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Toggle visibility of a ng-include depending on route - Stack Overflow

programmeradmin1浏览0评论

I have the following configuration:

$routeProvider
.when('/cars', { templateUrl: 'app/cars/index.html', controller: 'CarsCtrl', reloadOnSearch: false })
.when('/bikes', { templateUrl: 'app/bikes/index.html', controller: 'BikesCtrl', reloadOnSearch: false });

and somewhere in my root index.html there is a:

<a href="#/cars">Cars</a>
<a href="#/bikes">Bikes</a>
<div ng-view></div>

Now, I want both views loaded and generated in the DOM at the same time, and show one of them depending on the route/URL.

Something like the following (not actual working code, just to give you an idea).

app.js:

$routeProvider
.when('/cars', { controller: 'CarsCtrl', reloadOnSearch: false })
.when('/bikes', { controller: 'BikesCtrl', reloadOnSearch: false });

root index.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>

UPDATE: I know that ng-view kind of does this, but the difference, if subtle, exists. I want the html of each view to be generated once and stay in the DOM at all times.

I have the following configuration:

$routeProvider
.when('/cars', { templateUrl: 'app/cars/index.html', controller: 'CarsCtrl', reloadOnSearch: false })
.when('/bikes', { templateUrl: 'app/bikes/index.html', controller: 'BikesCtrl', reloadOnSearch: false });

and somewhere in my root index.html there is a:

<a href="#/cars">Cars</a>
<a href="#/bikes">Bikes</a>
<div ng-view></div>

Now, I want both views loaded and generated in the DOM at the same time, and show one of them depending on the route/URL.

Something like the following (not actual working code, just to give you an idea).

app.js:

$routeProvider
.when('/cars', { controller: 'CarsCtrl', reloadOnSearch: false })
.when('/bikes', { controller: 'BikesCtrl', reloadOnSearch: false });

root index.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>

UPDATE: I know that ng-view kind of does this, but the difference, if subtle, exists. I want the html of each view to be generated once and stay in the DOM at all times.

Share Improve this question edited Feb 28, 2013 at 2:46 dariofarzati asked Feb 28, 2013 at 2:28 dariofarzatidariofarzati 8,6466 gold badges30 silver badges28 bronze badges 1
  • It's not possible to accomplish this with ng-view. But the question is, why would you really want to do this. Is it because you would like to 'preprocess' each route so that it loads faster? Routing is already pretty fast, unless your controllers require some async data, in which case you would use 'resolve' inside the route definition object, plus some app initialization code for fetching async data in the background. – Stewie Commented Feb 28, 2013 at 8:48
Add a comment  | 

4 Answers 4

Reset to default 9

I created a single RouteCtrl to load all of your views via ng-include. ng-view is not used. I inlined the templates. The templates could contain their own ng-controller directives to pull in specific controllers.

<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 is still configured, but no template or controller is specified, causing the RouteCtrl to always be active. That controller listens for the $routeChangeSuccess event and manipulates the ng-show properties accordingly.

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

The idea for this solution is from @Andy.

I found another way, which I think is the simplest, quickest and most manageable:

How to set bootstrap navbar active class with Angular JS?

Which is:

Use ng-controller to run a single controller outside of the 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>

and include in controllers.js:

function HeaderController($scope, $location) 
{ 
    $scope.isActive = function (viewLocation) { 
        return viewLocation === $location.path();
    };
}

Instead of using ng-include, you should use ng-view;

This will display the content of either app/cars/index.html or app/bikes/index.html

<a href="#/cars">Cars</a>
<a href="#/bikes">Bikes</a>
<div ng-view></div>

See the Template section from http://docs.angularjs.org/tutorial/step_07

Use a service with a show directive:

<div ng-show="myService.isActive('/')">Show this when at default route</div>
<div ng-show="myService.isActive('/cars')">Show this when at cars</div>

Service:

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;
});
发布评论

评论列表(0)

  1. 暂无评论