0

The angular app receives data in an array. With that data, $compile is being used to create a angular directive. Example...

for(i = 0; i < trueTest.length; i++) {
    var test = trueTest[i];
    $scope.directiveData = {
       blockId: test.blockId,
       dataType: test.dataType,
       type: test.type,
       directiveType: test.directiveType
    };

    $compile("<my-directive block-id='{[{ directiveData.blockId }]}' block-data-type='{[{ directiveData.dataType }]}' block-type='{[{ directiveData.type }]}' block-directive-type='{[{ directiveData.directiveType }]}'></my-directive>")($scope.$new());
    elem.find('.SomeElement').append(el);
}

Custom directive my-directive has an isolated scope with values blockId, blockDataType etc...

Most imprtant value is blockId inside my-directive. It determines what kind of data is going to be displayed in that directive. The problem is that it seems that $compile creates elements after the loop finishes so in every directive that $compile creates, isolated scope property is always that last one created in the loop.

My guess is that $compile creates elements (directives) asynchronously so by the time the loop finishes, the directives are only then created with the current values of $scope.directiveData. Or, directives are created as plain DOM elements but the scope is created afterwards, thus creating scopes of all directives with the last value of directiveData object.

Could anyone explain what is actually going on here?

EDIT

Here is a jsFiddle link of the problem. It doesn't run beacuse the code is quite large and i can't recreate the problem in fiddle but I tried to comment it as much as possible.

Problem

SECOND EDIT.

So i did some console.log(). I putted a console.log() right after elem.find('.SomeElement').append(el); and one console.log('just print this') inside the directives controller. It seems that elements are created in the DOM before the controller is of the directive is called. That would mean that all the DOM elements are created before the scopes are assigned.

Am i wrong?

3
  • If you can't reproduce the problem in a minimal jsfiddle, then your approach is too large. You should be able to break out little chunks of logic that work independently. Commented Feb 27, 2015 at 20:10
  • Easier said that done. It's a very large project and this is the most minimal and simplest way I could do it. I think the true problem is why is $scope.$new(true) making the property bound with '=' undefined? Properties bound with '@' are just fine. Commented Feb 27, 2015 at 20:15
  • Perhaps someone will be able to just figure it out looking at this. Nonetheless, writing your code properly broken into small pieces is much easier. It just requires more forethought and understanding. I could probably solve the problem in minutes. Right now, I'm just not positive about the circumstance. Code samples that are rough portrayals of the real code leave too many questions. Commented Feb 27, 2015 at 20:19

1 Answer 1

1

The issue is that your assigning your directiveData in the same scope every time, so you're overwriting the previous object.

How about moving the scope creations at the beginning of the loop and assigning the object to that newly created scope ?

Also, I inverted the DOM append call and the $compile call. From my experience, it's better to do it that way (I might be wrong though).

for(i = 0; i < trueTest.length; i++) {
    var scope = $scope.$new();
    var test = trueTest[i];
    scope.directiveData = {
       blockId: test.blockId,
       dataType: test.dataType,
       type: test.type,
       directiveType: test.directiveType
    };

    var el = $("<my-directive block-id='{[{ directiveData.blockId }]}' block-data-type='{[{ directiveData.dataType }]}' block-type='{[{ directiveData.type }]}' block-directive-type='{[{ directiveData.directiveType }]}'></my-directive>");
    elem.find('.SomeElement').append(el);
    $compile(el)(scope);
}

I have not tested it, but it should be closer to working.

Sign up to request clarification or add additional context in comments.

5 Comments

Also, don't forget to destroy your created scopes when they are not used anymore (i.e. when you remove the DOM elements).
Maaan, this works beautifully. I didn't know that one can $compile() after append(). Simpy beautiful. Thank you very much.
@MarioLegenda Are you saying compiling after appending is what solved your problem? My answer was the same suggestion to create the new scope at the beginning... I deleted it because you said it didn't work.
@m56 Maybe it didn't work because he was still assigning the directiveData object to $scope, and not to the newly created scope.
I was creating the new scope like this $compile(el)($scope.$new()) but i had to create a new scope before that and assign the directiveData object to that new scope. I'm sorry if i didn't understand your answer.

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.