2

I have a directive which has this piece of code:

return {
    restrict: "E",
    scope: {
        moduleProgress: "=",
        modules: "=",
        parentScroll: "="
    },
    templateUrl: 'app/program/module.list.template.html',
    link: function(scope,el,attrs,ctrl,tf) {
        $templateRequest("app/program/chapter.list.template.html").then(function(template) {
            var template = angular.element(template);
            var elements = [];

            console.log(scope);

            attrs.$observe("modules", function(val) {
                scope.modules.forEach(function(module) {
                    module.open = false;
                });
            });

For some reason, the first time I navigate to the view that contains this directive everything works fine, but from the second time onwards I always get a Cannot call method 'forEach' of undefined error. I read through some similar questions on SO which mentioned interpolated attributes not being instantly available on the link function, so they reccomended the use of $observe. I even added a console.log(scope) and the modules property shows up on the object. Any idea of what might be causing this?

3
  • scope.modules is an array. And even if it wasn't a valid method, the problem is that it says my scope.modules property is undefined. Commented Jul 21, 2015 at 11:45
  • I think you only use $observe on attributes (which I'm pretty sure always return strings) that contain interpolation i.e. {{}}. So don't think that will work on an array. I might be wrong though. I've never needed to use it. Commented Jul 21, 2015 at 11:53
  • Yeah, $observe is only for interpolated (@) attributes I guess. Commented Jul 21, 2015 at 11:58

1 Answer 1

1

It should be rather $scope.$watch rather that attrs.$observe as $observe required @ in isolated scope of directive & on html it would be modules="{{module}}", For big object DOM will get messed up so I'd prefer you to use $watch which make sense

Code

scope.$watch("modules", function(newVal) {
    if(newVal){
        scope.modules.forEach(function(module) {
            module.open = false;
        });
    }
});
Sign up to request clarification or add additional context in comments.

3 Comments

That would be a solution. The problem was in my parent controller that defined $scope.modules after a promise, so in directive link time it wasn't available yet. I could $watch for the property or fetch the data on resolve, which is what I did. But thanks ;)
@Thiatt updated the answer..yes that if check will validate modules value is there or not, Glad to heard that it does helped..Do upvote please..Thanks :)
After a lifetime of debugging, I finally discovered that promised data was causing my link function to run with undefined values.

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.