2013-02-28 5 views
7

Я следующая конфигурация:Переключить видимость в нг-включает в зависимости от маршрута

$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> 

Теперь я хочу, как views загружен и сгенерирован в DOM одновременно и покажет один из них в зависимости от маршрута/URL.

Что-то вроде следующего (не фактический рабочий код, просто чтобы дать вам представление).

app.js:

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

корень 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: Я знаю, что нг-вид рода делает это, но разница, если тонкий, существует , Я хочу, чтобы html каждого представления был создан один раз и всегда находился в DOM.

+0

Это невозможно сделать с помощью ng-view. Но вопрос в том, почему вы действительно хотите это сделать. Это потому, что вы хотите «предварительно обработать» каждый маршрут, чтобы он загружался быстрее? Маршрутизация уже довольно быстрая, если только вашим контроллерам не нужны некоторые данные асинхронного ввода, и в этом случае вы должны использовать «разрешение» внутри объекта определения маршрута, а также код инициализации приложения для извлечения данных асинхронного ввода в фоновом режиме. – Stewie

ответ

9

Я создал один RouteCtrl, чтобы загрузить все ваши мнения через нг-включить. 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.

1

Вместо использования ng-include вы должны использовать ng-view;

Это будет отображать содержимое либо app/cars/index.html или app/bikes/index.html

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

Смотрите Template раздел из http://docs.angularjs.org/tutorial/step_07

+0

Привет, Паскаль, спасибо за ваш ответ! Однако это не то, что я ищу. Я уточнил в своем вопросе. ng-view будет переключать содержимое, да, но он делает это, удаляя содержимое из выходящего представления и вставляя содержимое для нового представления при каждом изменении маршрута. Я хочу, чтобы оба содержимого были уже обработаны и просто переключали ту или иную страницу с показом ng-show или CSS. – luisfarzati

+0

где/когда вы меняете 'carsVisible' и' bikesVisible', а у вас есть контроллер где-то в корневом 'index.html'? –

1

Используйте сервис с шоу директивы:

<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.ЯШ:

// this is run after angular is instantiated and bootstrapped 
myApp.run(function ($rootScope, myService) { 
    $rootScope.breadcrumbService = MyService; 
}); 
3

Я нашел еще один способ, который я думаю, это самый простой, быстрый и наиболее управляемым:

How to set bootstrap navbar active class with Angular JS?

Что:

Используйте нг-контроллер для запуска одного контроллер за пределами 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> 

и включить в co ntrollers.js:

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