Search code examples
angularjsangularjs-directiveangularjs-controllerangularjs-ng-include

Dynamic update of ng-include through controller and directive Angualar-js


Left side of the page sometimes have just info, sometimes it has side menu. When there is side menu, the content of main section depends on the option clicked.

Since the same kind of layout is used in multiple places, I created nested directives for the link/info side menu.

I have problem with the link option. Once link clicked, it calls the controller function to update the ng-include location of the main content holder. Controller does update the variable that holds the ng-include link, but ng-include does not include new template.

HTML: Left Side

<left-side hasmenu='hasMenu' update-tab='updateTab' options='menuOptions'></left-side>

Main Content area:

<div id="tabContentWrapper" class="left two-third-screen-tab " ng-include="tab">

Controller:

    var myStatsController = angular.module('myStatsController', []);

    myStatsController.controller('StatsCtrl',
    ['$scope', '$rootScope',function ($scope, $rootScope){

    //default tab
    $scope.tab = 'stats/views/stats.html';

    $scope.updateTab = function(newTab){
             $scope.tab=newTab;                   
            };

    //all tabs
    $scope.menuOptions =[{'text':'Stats','link':'stats/views/stats.html','isTab':true,'isFullScreen':false},
                {'text':'Summary','link':'stats/views/summary.html','isTab':true, 'isFullScreen':false}
    }]);

Directives: 1) Left Side directive HTML:

<div class="sideMenu left">
<div ng-switch="hasmenu" class="sideMenuNavSection">
    <side-menu ng-switch-when="true"  update-tab="updateTab(tab)" options='options'></side-menu>
    <side-info ng-switch-when="false" options='options'></side-info>
</div>
<home-button></home-button>

Directive code:

//left side area
myDirectives.directive('leftSide', function () {

return {
    restrict: 'AE',
    replace: true,
    scope:
    {
        options: "=",
        hasmenu:"=",
        updateTab:"&"

    },
    templateUrl: 'shared/leftSide.html'
};

});

2) Directive that choose what to display link or info sections:

//side navigation

myDirectives.directive('sideMenu', function ($compile) {

return {
    restrict: 'AE',
    scope: {
        options: "=",
        updateTab:"&"
    },
    link: function (scope, element, attrs) {


        for (var item in scope.options) {
            if (scope.options[item].isTab === true) {
                var link = scope.options[item];
                element.append('<tab-link update-tab="'+attrs.updateTab+'" fullscreen = "' + link.isFullScreen + '" linktext="' + link.text + '" options="' + link.link + '"></tab-link>');
            }
            else {
                // info section - not relevant for question
            }
            $compile(element.contents())(scope);
        }

    }
};

});

Finally Directive that constructs tabLink and calles controller function updateTab(newTab) to update $scope.tab for ng-include

myDirectives.directive('tabLink', function ($compile) {

return {
    replace: true,
    restrict: 'AE',
    scope: {
        options: "@",
        linktext: "@",
        fullscreen: "@",
        updateTab:"&"
    },
    template: '<div class="infoText narrow "><div class="sideMenuItem bold"><a href="javascript:void(0);">{{linktext}}</a></div><div class="greenArrow"></div></div>',
    link: function (scope, element, attr) {

        var tab = document.getElementById('tabContentWrapper');
        tab = angular.element(tab);

        element.on('click', function (event) {

            //calls controller function
            scope.updateTab()(scope.options);
            $compile(tab.contents())(scope);  
        }); 
    }
};
});

Thanks


Solution

  • Because you are initiating this thing with a normal element on click, It doesn't invoke the digest cycle. Add $scope.$apply() after $scope.tab=newTab;