-1

Note: I am modifying this question to improve rating.

I developed the following directive with isolated scope:

app.directive('outerIsolated', function () {
    return {
        restrict: 'A',
        scope: {
            theData:'=',
            ...
        },
        replace: true,
        templateUrl: './photo-list-template.html',
        link: function ($scope, elm, attrs) {
           ...
           ...
           ...
        }
    };
});

And also, I developed the following inner directive with inherited scope.

app.directive('innerInherited', ['$compile', '$timeout', '$parse', function ($compile, $timeout, $parse) {
    return {
        scope: false;
        link: function (scope, el, attrs, ngModel) {
           ...
           ...
           ...            }
    };
}]);

The Problem:

If I use the directive outerIsolated as a parent directive for the inner directive innerInherited, then all references to inherited scope variables won't work.

The innerInherited directive works just fine on its own and has been used extensively. Now, I can't change it to isolated scope. This directive is actually called check-if-required and will loop across all child input fields to find out if anyone is required field, and make it required.

Just few days ago, I learned about directive with isolated scope which can be used to develop reusable components. I liked the idea, and I developed one call upload-photo-list which I referred to it here as outerIsolated.

Is there anyway I can solve this problem easily?

One direct way, is reverse the nesting of the directive. So, I tried to use directive with inherited scope in the outer level instead, but, the problem now is that the link function of the outer directive didn't see the elements of the inner directive after being replaced by the template. I even used this code to try to wait until the document is ready this this:

angular.element(document).ready(function (){...}

... but still, the outer directive cannot reach the HTML Elements generated by the inner directive.

Appreciate your help to find a solution.

Thank you.

Old Question:

Note: this part is obsolete. I kept it here for tracking purposes only.

I am building a simple example using ng-signature-pad and signature-pad plugins.

Click here to see the sample HTML file as per the download

I noticed that the following script tag works only if I place them before the </body> tag (same as the provided sample source code in the link above):

  <script src="js/app.js"></script>

If I place the above script tag in the <head> tag it is not affected.

Could someone explain to me why?

tarekahf
  • 738
  • 1
  • 16
  • 42
  • 1
    Your question is a little confusing. You said "If I place them *in* the tag..." The example shows the script tags *in* the body tag. What tag are you referring to in your question? – spdaly Aug 26 '16 at 18:39
  • I corrected the question. Appreciate your feedback. – tarekahf Aug 26 '16 at 18:41
  • The reason for placing scripts at the end of the body is to ensure the DOM is loaded before running the script. If you move it to the head, the DOM is not loaded, and therefore elements are not available for manipulation, which is likely why it is failing. – Heretic Monkey Aug 26 '16 at 18:49
  • 1
    Possible duplicate of [Where is the best place to put – Heretic Monkey Aug 26 '16 at 18:50
  • the script tag itself works in both places, the problem is your code. – Kevin B Aug 26 '16 at 18:52

2 Answers2

0

I would need to look at the project you are referencing in more detail, but I would imagine that the library and the app.js that you are using are referencing elements on the page.

If you have the scripts in the HEAD tag, those elements are not there. By putting them at the bottom of the BODY element, you are ensuring that the elements are in fact in the browser.

spdaly
  • 1,260
  • 2
  • 18
  • 35
  • Why the downvote? Essentially a summary answer of the comments on the question... – spdaly Aug 26 '16 at 19:11
  • Thanks a lot! That was so smart being able to analyze the situation without seeing the code. You are absolutely right. This is same effect of jQuery document ready code block, to make sure all elements are created before they are accessed by code. This is not possible in AngularJS, so this weird technique will do. Even w3schools.com recommneds putting the script tag before `

    ` tag.

    – tarekahf Aug 29 '16 at 19:24
  • I have changed the question. Appreciate your feedback. – tarekahf Mar 01 '17 at 22:15
0

The quickest way to solve my problem is as follows...

I had to use the directive with the inherited scope check-if-required to be on the outer level, and the directive with the isolated scope upload-photo-list in the inner level.

However, I had to make two modifications for the directive check-if-required:

  1. Add $timeout in the link function to ensure the inner directive has finished rendering its HTML before looping through all the input elements as follows:

code:

var children;
$timeout(function() {
    children = $(":input", el);
    el.removeAttr('check-if-required');
    angular.forEach(children, function(value, key) {
        ...
        ...
    });
})
  1. Must compile the element with respect to the scope of the element:

code:

angular.forEach(children, function(value, key) {
    if(typeof (value.id) != 'undefined') {
        if (scope.isFieldRequired(value.id)) {
        angular.element(value).attr('required', true);
        $compile(value)(angular.element(value).scope());
    }
})

So far, this solution works well for me.

Any feedback to improve is welcomed.

Tarek

tarekahf
  • 738
  • 1
  • 16
  • 42