1

I am trying to read properties set on an element by ng-repeat using another custom element:

<div foo ng-repeat="img in [{image: 'images/img1.jpg', text: 'some text'},{image: 'images/img2.jpg', text: 'some text'}]">
    <img ng-src="{{img.image}}"/>
    <p>{{img.text}}</p>
</div>

app.directive('foo',function() {
  return {
    restrict : 'A',
    scope: {},
    link:function (scope, element, attrs) {
      var imageNode = element.find('img');
      var textNode = element.find('p');

      var image = {
        url: imageNode.prop('src'),
        text: textNode.html()
      };

      console.log(image);
    }
  };
});

Since the ng-repeat runs before the custom directive, the DOM should be inserted with the 2 elements by the time the link function of 'foo' kicks in. In such case, the link function of 'foo' should fire twice with element as the inserted DOM by ng-repeat.

The problem is that imageNode.prop('src'); has the value "{{img.image}}" and not the evaluation of the expression.

Can anyone help me understand what exactly is happening under the hood.

Plunker example - https://plnkr.co/edit/E9JHhZUf2h7B6FVeXRK4?p=preview

EDIIT

The example above is trivial but what i wanted to understand is the flow of the directive execution. There are ways of getting the data to the foo directive but that's not the final objective.

According to my understanding, since ng-repeat and foo are defined on the same element, the execution order will be
1) compile of ng-repeat because ng-repear has a priority of 1000
2) compile of foo since foo has a default priority of 0
3) link of foo since link executes in reverse priority order
4) link of ng-repeat

since ng-repeat uses transclude, it sucks out the DOM during the compile phase and is added again during its link phase.

If that is the case, the link function of foo that is executing before link of ng-repeat should have nothing but the comment inserted by transclude as its element as the DOM is not yet added. But that's not the case. I can access the two newly added DOM elements added by ng-repeat in foo's link phase. What am i missing?

Also, if i am not wrong, the expressions are evaluated during the link phase, so if the new elements are reinserted by ng-repeat which happens during link phase, the expressions should have also been evaluated and the {{img.text}} should have been converted to "some text" during the link phase of ng-repeat which is not happening but when i do element[0] that is i can see the value {{image.text}} being replaced. Am i again missing something?

1
  • You should use the attrs value to extract the data bound to the given DOM element. Commented Apr 29, 2016 at 19:19

3 Answers 3

1

you can pass image data in directive as attribute

<div foo data='obj' ng-repeat="img in [{image: 'images/img1.jpg', text: 'some text'},{image: 'images/img2.jpg', text: 'some text'}]">
    <img ng-src="{{img.image}}" />
    <p>{{img.text}}</p>
 </div>




app.directive('foo',function(){
  return{
    restrict : 'A',
    scope:{},
    link:function(scope,element,attrs){;

      var image = {};
      image.url = attrs.data.image
      image.text = attrs.data.text
      console.log(image);
    }
  }
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for reverting but the aim is not just to pass the data but to understand the directive execution flow. I have edited the above question to add some more details
0

If you're simply trying to pass in the url and text, why not just add them to the scope?

just change the html to :

  <div foo text={{img.text}} image-url={{img.image}} ng-repeat="img in [{image: 'images/img1.jpg', text: 'some text'},{image: 'images/img2.jpg', text: 'some text'}]">

and the dierctive to :

  app.directive('foo',function(){
  return{
    restrict : 'A',
    scope:{
      text: '@',
      imageUrl: '@'
    },
    link:function(scope,element,attrs){;

      console.log(scope.text);
      console.log(scope.imageUrl);
    }
  }
});

see modified plunkr : https://plnkr.co/edit/0gw7uom9BGjFGJQ9e20E?p=preview

2 Comments

Thanks for reverting but the aim is not just to pass the data but to understand the directive execution flow. I have edited the above question to add some more details
@YatinGera you might consider posting a different question, because you are asking an entirely different question :)
0

If you want to pass the data of the repeat to an attribute and use it in the directive try like this

<div foo imgdata="img" ng-repeat="img in [{image: 'images/img1.jpg', text: 'some text'},{image: 'images/img2.jpg', text: 'some text'}]">
    <img ng-src="{{img.image}}" />
    <p>{{img.text}}</p>
 </div>


app.directive('foo',function(){
  return{
    restrict : 'A',
    scope:{
        imgdata: '='
    },
    link:function(scope,element,attrs){;

      console.log(scope.imgdata);
    }
  }
});

this fiddle shows the way

hope this helps

1 Comment

Thanks for reverting but the aim is not just to pass the data but to understand the directive execution flow. I have edited the above question to add some more details

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.