Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I $watch multiple interpolated attributes in a directive?

I don't understand how to watch multiple attributes at the same time in the link function, so I create an object with all the parameters and I watch for it. But I noticed that the attribute in the link function is a string and not an object so I'm using angular.fromJson(val).

All the example I found just use one parameter

Could you explain how to watch multiple attributes?

Thanks

EDIT: I cannot use attrs parameter because I need to bind the attributes -- i.e., they require interpolation. For example

<ul class="thumbnails">
    <li class="span3" ng-repeat="image in currentSizeInfo.images" >
       <upload-file info = "{{getInfo($index)}}" foo="foo$index" ></upload-file>
    </li>
</ul>

I think that I have to use $watch

link:function (scope, element, attrs ) {
    scope.$watch('info', function (val) {
    // if info is and foo is .... do all the stuff
    })
}
like image 924
heckmac Avatar asked Oct 19 '12 14:10

heckmac


1 Answers

I'm not sure I fully understand your question, so please correct me if I misunderstand. Are just want to pull values from multiple attributes on your directive? So say you have a HTML like this:

<my-directive attr1="data1" attr2="data2" attr3="data3" />

And you want to get the values of those different attributes? In the link function, you just use the attrs parameter. For example:

link: function(scope, element, attrs) {
    var foo1 = attrs.attr1;
    var foo2 = attrs.attr2;
    var foo3 = attrs.attr3;
}

You can also use the scope property on the directive to automatically bind attributes to your scope. See their documentation on directives. So, something like this:

scope: {
    attr1: '@',
    attr2: '@',
    attr3: '@'
}

And then those properties end up in your scope automatically. However, as I found out, those values aren't always in the scope when you'd expect. So you can use the $watch function to do what you need with them. Something like:

link: function(scope, element, attrs) {
    scope.$watch("attr1", function () {
         if (scope.attr1)
         {
              //stuff with attr1
         }
    }
    scope.$watch("attr2", function () {
         if (scope.attr2)
         {
              //stuff with attr2
         }
    }
    //....
}

If you need to use them all together at the same time, you could use a function for the first parameter of the $watch that returns a string that would be different once they are all there and then put your logic in the function that is the 2nd parameter. So something like this:

link: function(scope, element, attrs) {
    scope.$watch(function () {
        if (scope.attr1 && scope.attr2 && scope.attr3)
        {
            return "allSet";
        }
        else
        {
            return "";
        }
    }, function (newVal) {
        if ("allSet" == newVal)
        {
            //do stuff with all the properties
        }
    });
}

If you're wanting to bind objects into your scope, you can use '=' instead of '@'. Another option is '&' which evaluates a function in the parent scope. This is all explained in the directive documentation linked above.

like image 102
dnc253 Avatar answered Oct 14 '22 03:10

dnc253