Ndrou
Ndrou

Reputation: 169

Passing element attributes from parent to child with Angular JS 1.3

I have a problem with Angular JS. I have two directives.

angular.module('myModule', [])
    .directive('myFirstDirective', function(){
        return {
            link: function (scope, elem, attr) {
                var myAttributeToPass = attr.myFirstDirective;
                scope.myAttr = myAttributeToPass;
            },
            controller: 'MyFirstController'
        }
    })
    .controller('MyFirstController', function($scope){
        this.returnTheParameter = function(){
            return $scope.myAttr;
        }
    })
    .directive('mySecondDirective', function(){
        return {
            require : ['ngModel', '^myFirstDirective'],
            link : function($scope, element, attrs, ctrls) {
                var ngModel = ctrls[0];
                var myFirstCtrl = ctrls[1];

                var theParamOfFirst = myFirstCtrl.returnTheParameter();
            }
        }
    });

I init my first value with a string :

<div my-first-directive="foobar"> (... => my second directive is inside) </div>

My problem is in the life cycle, the returned value is always undefined because the controller is called before the link. When i do an isolated scope, with :

scope: {
    "myProp": "@myFirstDirective"
}

That's works but i don't want to isolate the scope...

Any ideas ?

Thanks a lot !

Upvotes: 2

Views: 879

Answers (1)

Matt
Matt

Reputation: 1023

The problem lies in the order in which the operations are taking place.

It sounds like you will need to compile things in a specific order. In which case I would like to refer you to this post: How to execute parent directive before child directive? so I don't borrow the full thunder of another person's explanation.

Ultimately you would want to do something along the lines of:

    return {
        compile: function(){
          return{
            pre:function (scope, elem, attr) {
              var myAttributeToPass = attr.myFirstDirective;
              scope.myAttr = myAttributeToPass;
          },
            post: angular.noop
          };
        },
        controller: 'MyFirstController'
    };

for your first directive and for the second directive:

    return {
        require : ['^myFirstDirective'],
        compile: function(tElement, tAttrs, transclude){
          return{
            pre: angular.noop,
            post: function($scope, element, attrs, ctrls) {
              var ngModel = attrs.ngModel;
              var theParamOfFirst = ctrls[0].returnTheParameter();
            }
          };
        }
    };

The angular.noop above is just an empty method returning nothing. For a working example feel free to browse the plunk I threw together (http://plnkr.co/edit/pe07vQ1BtTc043gFZslD?p=preview).

Upvotes: 1

Related Questions