2013-07-23 2 views
29

На данный момент у меня есть приложение с боковой панелью, а боковая панель загружает различные html-шаблоны с использованием ng-include, основываясь на том, какую операцию пользователь хочет сделать. Это карта, связанных с приложением, так, например, если пользователь выбирает кнопку «Добавить Нога» будет загружаться add_leg.html шаблон в боковую панель, используя ng-include:Контроллеры динамической загрузки и ng-include

// The Javascript code: 
$scope.addLeg = function() { 
    $scope.sidebar = true; 
    $scope.sidebar_template = '/partials/legs/add_leg.html';  
} 

// Simplified example of HTML: 
<html> 
<div ng-app="MyApp" ng-controller="MainCtrl"> 
    <a ng-click="addLeg()">Add Leg</a> 
    <a ng-click="addRoute()">Add Route</a> 
    <a ng-click="editLeg()">Edit Leg</a> 
    <a ng-click="editRoute()">Edit Route</a> 
    ... 

    <div id="sidebar" ng-class="{'sidebar-hidden': sidebar == false}"> 
     <div ng-include src="sidebar_template"></div> 
    </div> 

    <google-map></google-map> 
</div> 

Это все хорошо и работает как хотелось бы, но на данный момент мое приложение использует только один контроллер (MainCtrl в js/controllers.js), и он начинает действительно захламлять. Сейчас у меня много методов, потому что функциональность приложений расширяется. Я хотел бы разделить контроллер на несколько контроллеров, сохраняя при этом эту функциональность боковой панели.

Я хочу иметь MainCtrl как главный контроллер, который управляет загрузкой шаблона боковой панели (путем изменения переменной sidebar_template, указывающей на место назначения файла), и я хочу, чтобы он контролировал некоторые глобальные связанные с картой методы (например, выборка пригородов из координат и т. д.).

Я пытался разбить его так:

controllers/js/main.js - MainCtrl 
controllers/js/legs.js - LegCtrl 
controllers/js/routes.js - RouteCtrl 

Я хочу LegCtrl и RouteCtrl, чтобы наследовать MainCtrl таким образом я могу получить доступ к его масштабы и методы, что все в порядке. Но теперь проблема заключается в том, как я динамически загружаю контроллер в div на боковой панели, исходя из того, какая функциональность требуется. Первоначально все мои методы были в , и это на обертке div, которая окружает div боковой панели (см. Выше для примера), поэтому это не проблема.

Например, скажем, я нажимаю кнопку «Добавить Нога», это будет необходимо вызвать addLeg в LegCtrl, но LegCtrl не загружен на приложение, так что он не имеет доступа к методу. Я мог бы сохранить addLeg() внутри MainCtrl и попросить его изменить переменную sidebar_template, чтобы загрузить шаблон, но ничего в шаблоне не будет работать, потому что он вызывает методы изнутри LegCtrl.

мне нужно как-то динамически загружать контроллер на ng-include DIV в боковой панели, что-то вроде этого, может быть:

// MainCtrl 
$scope.addLeg = function() { 
    $scope.required_controller = LegCtrl; 

    $scope.sidebar = true; 
    $scope.sidebar_template = '/partials/legs/add_leg.html';  

    LegCtrl.addLeg(); 
} 

<div id="sidebar" ng-class="{'sidebar-hidden': sidebar == false}"> 
    <div ng-include src="sidebar_template" ng-controller="{{required_controller}}"></div> 
</div> 

В нерабочем приведенном выше примере вы можете увидеть возможное решение, я думал о, но Мне нужно LegCtrl быть фактической функцией контроллера, а не объектом (для работы ng-controller). Мне также нужен способ позвонить addLeg на LegCtrl с MainCtrl.addLeg (возможно, используя широковещательную рассылку?).

Если кто-то может указать мне в правильном направлении, это было бы здорово. Извините за огромный пост, ему нужно было немного объяснить, чтобы сделать его связным. Надеюсь, это имеет смысл. Благодарю.

Обновление: Я думаю, что я нашел решение, использующее сервис для управления навигацией (он загрузит соответствующие шаблоны и передаст событие новому динамику, который будет динамически загружен, чтобы сообщить ему, какую функцию выполнять):

http://plnkr.co/edit/Tjyn1OiVvToNntPBoH58?p=preview

Просто пытаюсь проверить эту идею сейчас, но трансляция .on не работает.Я думаю, это связано с тем, что трансляция запускается до загрузки шаблона. Как я могу это исправить? Является ли это хорошим решением для того, что я делаю?

+0

Я видел ваш плункер и отредактировал его, чтобы включить в консольные сообщения. Он покажет вам, что событие опубликовано первым, а затем слушатель начинает слушать. Это происходит потому, что каждая вещь лениво загружается в угловое приложение. http://plnkr.co/edit/rWZ3x2Jzk9EV3OpD1HF1?p=preview –

ответ

12

Если я правильно понял, что вы можете попробовать, это создать шаблонный вид специально для создания новой ноги.

От главного контроллера реализовать определенную логику, чтобы показать шаблон

$scope.addLeg=function() { 
    $scope.showAddLeg=true; 
} 

Вид шаблона AddLeg загрузит контроллер и, следовательно, обеспечить механизм на самом деле добавить новую ногу. Шаблон будет выглядеть

<script type="text/ng-template" class="template" id="addLegTemplate"> 
    <div ng-controller='LegsController'> 
    <!--html for adding a new leg--> 
    </div> 
</script> 

Вы можете включить этот шаблон внутри вас основной HTML с помощью нг-если + нг-включить.

<div ng-if='showAddLeg'><div ng-include='addLegTemplate'/></div> 

В принципе, вы можете создать несколько видов и привязать их к одному контроллеру (но экземпляр будет отличаться). В этом случае LegsController может быть привязан к нескольким представлениям для поддержки полной функциональности.

+0

Проблема заключается в том, что я загружаю новые шаблоны, связанные с функциональностью нога (т. е., возможно, на шаблоне addLeg есть кнопка для загрузки шаблона editLeg), когда они переключают шаблоны, у него будет свое собственное определение контроллера в новом контроллере (и, следовательно, потеряет область, и все переменные состояния будут потеряны). – andro1d

+0

Вы можете поделиться моделью, оставив ее вне контроллеров и передав ее как часть ng-init. – Chandermani

+0

эй Чандермани, вы можете взглянуть на мое обновление? Благодарю. – andro1d

4

Я раздвоенный свой plunkr демо в тот, который я считаю, делает то, что вы ищете: http://plnkr.co/edit/whsjBT?p=preview

Это показывает событие транслируется с одного контроллера на другой после 2-го контроллера (LegCtrl в нашем примере) загружается через ng-include и передает данные.

Я использовал $includeContentLoaded событие от ng-include, чтобы отсрочить вещание события до тех пор, пока не будут выставлены угловые отчеты о загрузке add_leg.html. Кроме того, я думаю, что были некоторые проблемы с тем, как вы используете $broadcast() ... это первый параметр должен быть таким же, как используемый в $on() в LegCtrl

Другая идея рассмотреть просто использует себя ваш сервис Navigation обмениваться состояния между контроллеры, если это подходит в вашем сценарии.

+0

Это именно то, что я искал. Огромное спасибо! –

5

Мне нравится этот сценарий данных инициативе, просто манипулировать строки в шаблонах:

$scope.templates = [ 
    { name: 'include1.html', url: 'partials/include1.html' } 
]; 
$scope.addTemplate = function(name, url) { 
    $scope.templates.push({ name: name, url: url }); 
}; 

и разметку:

<div ng-repeat="template in templates" ng-include="template.url"></div> 

Чтобы добавить или удалить точки зрения, просто изменить шаблоны и вуаля! Если вам нужно больше кода контроллера, вы можете включить ссылку на скрипт в include. Я предполагаю, что могут быть сложности с привязкой к данным в частичном представлении, но компиляция $ должна их разрешать.

Смежные вопросы