Подтвердить что ты не робот

Контроллеры динамической загрузки и ng-include

В настоящее время у меня есть приложение с боковой панелью, а боковая панель загружает разные html-шаблоны с помощью ng-include на основе той операции, которую пользователь хочет сделать. Это приложение, связанное с картой, например, если пользователь выбирает кнопку "Добавить ногу", он загрузит шаблон add_leg.html на боковой панели с помощью 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 in 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 на боковой панели, исходя из того, какая функциональность требуется. Первоначально все мои методы находились в MainCtrl, а на обертке 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 не работает. Я думаю, это потому, что трансляция срабатывает до загрузки шаблона. Как я могу это исправить? Является ли это хорошим решением для того, что я делаю?

4b9b3361

Ответ 1

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

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

$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, используя ng-if + ng-include.

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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