sajan
sajan

Reputation: 1370

Angular js Nesting custom directives

I want to use something like nesting with custom directives in angular js. Could anyone explain me with simple solution ?

example code is below is not working for me :

<outer>
    <inner></inner>
</outer>

JS

var app = angular.module('app',[]);
app.directive('outer',function(){
    return{
        restrict:'E',
        template:'<div><h1>i am a outer</h1></div>',
        compile : function(elem,attr){
            return function(scope,elem,att,outercontrol){
                outercontrol.addItem(1);
            }
        },
        controller : function($scope){
            this.addItem = function(val){
                console.log(val);
            }
        }
    }
});

app.directive('inner',function(){
    return{
        require : 'outer',
        template : '<div><h1>i am a inner</h1></div>',
        link:function(scope,elem,attr){

        }
    }
});

Upvotes: 21

Views: 15930

Answers (2)

Peter Ashwell
Peter Ashwell

Reputation: 4302

If you want a simple solution, check out this plunkr.

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

app.directive('outer', function() {
    return {
        restrict: 'E',
        template: '<div style="border-style:solid"><h1>hey</h1><inner></inner></div>',
    }
});

app.directive('inner', function() {
    return {
        restrict: 'E',
        template: '<div style="border-style:solid"><h1>i am an inner</h1></div>',
    }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.js"></script>
<div ng-app="app">
  <outer></outer>
</div>

The problem is that you're nuking the tag with the template attribute of the directive. This line:

    template:'<div><h1>i am a outer</h1></div>',

Does that.

Upvotes: 4

Mostafa Ahmed
Mostafa Ahmed

Reputation: 661

First add restrict:'E' to the inner controller to make it accessible as an element.

Then change the require : 'outer' into require : '^outer', to enable looking for this directive in parents.

Then you need to use transclude to enable the content of the <outer> to be viewed, by the following steps:

  1. add transclude = true to the outer directive.
  2. define where you want the inner data to be viewed. (I guess you need it to appear after the "i am outer" string so you can modify the template of the outer one to be like this template:'<div><h1>i am a outer</h1><div ng-transclude></div></div>').

Then you don't need to the compile parameter at all. As this variable which called outercontrol will not be called at the outer directive but at the inner directive so there is no need to the compile at all for the outer directive and the inner link function will be modified to be like this:

link: function(scope, elem, attr, outercontrol){
    outercontrol.addItem(1);
}

after all this modification the final code will be like the following:

the HTML:

<outer>
<inner></inner>
</outer>

the js:

var app = angular.module("exampleApp",[]);
    app.directive('outer', function(){
        return{
            transclude:true,
            restrict:'E',
            template:'<div><h1>i am a outer</h1><div ng-transclude></div></div>',
            controller : function($scope){
                this.addItem = function(val){
                    console.log(val);
                }
            }
        }
    });

    app.directive('inner',function(){
        return{
            restrict:'E',
            require : '^outer',
            template : '<div><h1>i am a inner</h1></div>',
            link:function(scope,elem,attr,outercontrol){
                outercontrol.addItem(1);
            }
        }
    });

Upvotes: 47

Related Questions