Как обновить директиву об изменениях состояния


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

.state(‘root', {
            abstract: true,
            url: ‘/root',
            templateUrl:  ‘views/root.html',
        })

root.html включает в себя sidebar.html, который имеет динамическое меню, вызываемое через директиву следующим образом:

sidebar.html

  <ul class="nav" id="side-menu">
        <li class="nav-header">
                <img alt="avatar" ng-src="{{ avatar }}" />
        </li>

        <!—Dynamic Menus Directive -->
        <li sidebar-menus></li>
    </ul>

Директива показывает меню, основанное на $state.includes(). Но что происходит, директива показывает нормально в первой загрузке, но она не обновляет директива при изменении состояния. Чтобы решить эту проблему, я попробовал следующие методы, но ничего не вышло:

  1. добавил $state в scope в Главном контроллере, но это по-прежнему не меняет директиву как только он будет скомпилирован первым.
  2. пытался добавить $stateChangeSuccess watcher для запуска перекомпиляции директивы, но это не так перекомпилировать снова после первого раза (или) может быть, это перекомпиляция, но изменения не видны в шаблоне (это код, который у меня сейчас есть который я приведу ниже).
  3. перемещение боковой панели внутрь отдельного дочернего элемента состояния вместо того, чтобы иметь его в корневом состоянии работает, но он бьет цель так как я пытаюсь загрузить общую структуру в корень состояние первое и только обновить разделы меню в последующем состоянии изменения.

Я не совсем уверен, как подойти к этому. Я чувствую, что мой подход может быть неуместным и надеюсь, что кто-то сможет направить меня сюда. Это мой директивный код на данный момент:

.directive('sidebarMenus', ['$compile', '$state', '$rootScope',
    function($compile, $state, $rootScope) {

    return {
        restrict: 'A',
        replace: true,
        link: function(scope, element, attrs) {

            var state = scope.$state; // Scope from Main Controller

            // HTML Template
            function contructHtml(state) {

                var htmlText = '';

                // First Child State
                if (state.includes('root.child1')) {
                    var htmlText =  '<li>Child 1 Menu</li>';
                }
                // Second Child State
                if (state.includes('root.child2')) {
                    var htmlText =  '<li>Child 2 Menu</li>';
                }
                // Third Child State
                if (state.includes('root.child3')) {
                    var htmlText =  '<li>Child 3 Menu</li>';
                }

                $compile(htmlText)(scope, function( _element, _scope) {
                            element.replaceWith(_element);
                });

            } 

            $rootScope.$on('$stateChangeSuccess', function() {
                    var state = scope.$state; // scope.$state is added in main controller 
                    contructHtml(state);
             });

             // Initial Load 
             contructHtml(state);
        }
    }
}])
1 3

1 ответ:

Вы можете избавиться от компиляции с помощью шаблона. Ваш шаблон может выглядеть примерно так:

<li ng-if="state.includes('root.child1')">Child 1 Menu</li>
<li ng-if="state.includes('root.child2')">Child 2 Menu</li>
<li ng-if="state.includes('root.child3')">Child 3 Menu</li>

Таким образом, ваш код директивы должен выглядеть sth следующим образом

return {
    restrict: 'A',
    replace: true,
    template:'<div> <li ng-if="state.includes('root.child1')">Child 1 Menu</li>
              <li ng-if="state.includes('root.child2')">Child 2 Menu</li>
              <li ng-if="state.includes('root.child3')">Child 3 Menu</li>     
              </div>'
    link: function(scope, element, attrs) {

        $scope.state = scope.$state; // Scope from Main Controller

        $rootScope.$on('$stateChangeSuccess', function() {
            $scope.state = scope.$state; // scope.$state is added in main controller 
        });
    }
}