问题
I have a root state that defines the overall structure of the Angular template. In the root state, I have the sidebar included that has dynamic menus via directive that changes based on the state. Like this:
.state(‘root', {
abstract: true,
url: ‘/root',
templateUrl: ‘views/root.html',
})
root.html
includes the sidebar.html
that has dynamic menu called through Directive like this:
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>
The directive shows the menu based on $state.includes()
. But what happens is, the directive shows fine in the first load but it doesn’t update the directive during state changes. To resolve this, I tried the following methods but nothing worked:
- Added the
$state
toscope
in Main controller but it still doesn’t change the directive once it is compiled first. - Tried adding
$stateChangeSuccess
watcher to trigger recompiling the directive, but it doesn’t recompile again after the first time (or) maybe it is recompiling but the changes are not seen in the template (this is the code I have now which I will give below). - Moving the sidebar inside separate child states instead of having it in root state works, but it beats the purpose since I am trying to load the overall structure in the root state first and only refresh the menu sections in subsequent state changes.
I am not really sure how to approach this. I have a feeling my approach can be out of whack and hoping someone can guide me here. This is my directive code at the moment:
.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:
You can get rid of the compile business by using template. You template could look something like this:
<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>
So your directive code should look sth like this
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
});
}
}
来源:https://stackoverflow.com/questions/33807163/how-to-update-directive-on-state-changes