gkrishy
gkrishy

Reputation: 756

How to load and compile directives dynamically?

I'm having one scenario in angular js.

I'm having one main drop down with the items as 'sub-list' and 'sub-dropdown'. I have loaded the sub-list and sub-dropdown using directive.

Now my scenario is simple, On select of sub-list from drop down, I want to load the 'list-directive' and on select of sub-dropdown from the main drop down, I want the result as 'dropdown-directive'

It should happen dynamically.

My Seeddata.js:

var dirType = [
{ text: 'List', value: 0 },
{ text: 'Table', value: 1 },
{ text: 'Dropdown', value: 2 }
];

My Directives

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

directiveModule.directive('payerListDirective', function (payerService) {
return {
    restrict :"AC",
    template: "<ul><li ng-repeat='payer in dirType'>{{payer.text}}</li></ul>",
    link: function ($scope) {
        $scope.payersDir = payerService.getPayers();
    }
  };
});
directiveModule.directive('payerDropdownDirective', function (payerService)
{
return {
    restrict: "AC",
    template: "<select ng-model='x' ng-options='payer.value as payer.text for payer in dirType' ></select>",
    link: function ($scope) {
        $scope.payersDir = payerService.getPayers();
    }
};
});

Note: payerService is a factory that I Injected from Service Module to load the data

My View

<div ng-controller = "dircntrl" >

<select ng-model = "dirdummy">
<option ng-repeat = "dir in dirType" value = "{{dir.value}}" >{{dir.text}}     </option>
</select>
<div parent-directive></div> // This is the place where I need solution

My Controller

cntrlModule.controller('dircntrl', function ($scope) {
$scope.dirType = dirType;
$scope.$watch('dirdummy',function(){
    // Want the solution here
})
});

I was trying with $watch in controller to load the result. But i don't know the exact method to do this.

Upvotes: 1

Views: 848

Answers (2)

Ajay Kumar
Ajay Kumar

Reputation: 5243

Below are snippet code of loading directive dynamically on doLogin click event. at last line of code, enabled Model div after it placed inside the body.

    var app = angular.module("myapp",)
    app.directive("myLoginModel",function(){
        return {
            restrict:'E',
                template:'login.html',
                controller: 'myLoginController'
        }
    })


    app.controller("myDashboardController",function($compile){

        $scope.doLogin = function($scope){  
            var findTarget = $("body"),
            var compiled = $compile('<my-login-model></my-login-model>')($scope);
            findTarget.append(compiled);
            // Once Login Model directive is compiled and placed inside body section, then
            // enabled Model layout to show.
            setTimeout(function() {
                    $("#loginModel").modal("show");
                    this.$scope.$apply();
            }, 100);
        }
    })

Upvotes: 0

Joy
Joy

Reputation: 9560

Check working demo: JSFiddle.

You don't need to $watch. Use ng-if to load different directives dynamically. After you select an option, the corresponding directive will be loaded.

Note: ng-if will remove/create the DOM every time. So after you select a different option, the current DOM is removed and a totally new DOM element is inserted.

angular.module('Joy', [])
    .controller('JoyCtrl', ['$scope', function ($scope) {
        $scope.choice = '0';
    }])
.directive('firstDirective', function () {
    return {
        restrict: 'A',
        template: '<div>First directive</div>'
    };
})
.directive('secondDirective', function () {
    return {
        restrict: 'A',
        template: '<div>Second directive</div>'
    };
});

HTML:

<div ng-app="Joy" ng-controller="JoyCtrl">
    <select ng-model="choice">
        <option value="0" name="0">Zero</option>
        <option value="1" name="0">One</option>
    </select>
    <div>Selected: {{ choice }}</div>
    <div ng-if="choice==='0'" first-directive></div>
    <div ng-if="choice==='1'" second-directive>Second</div>
</div>

Update 1

If you wish to compile the directive at real time (although not recommended), you are able to use the $compile service to achieve it: JSFiddle.

The key is: use ng-change to call a function, which compile corresponding directive:

var $container = $('#result');
var directiveNames = [
    'payer-list-directive', 
    'payer-dropdown-directive', 
    'payer-dropdown-directive'
];
$scope.changeMe = function () {
    var $ele = $compile('<div ' + directiveNames[$scope.dirdummy] + '></div>')($scope);
    $container.html($ele);
};

In HTML:

<select ng-model="dirdummy" ng-change="changeMe()">

Upvotes: 3

Related Questions