Reputation: 117
I have a custom draggable directive inside of an ng-repeat of images. I want to store the x,y offset of each image after it has been dragged. Therefore, I need the directive to update a field on the image.
return {
restrict: 'A',
scope: false,
link: function(scope, element, attrs){
element.draggable({
containment: "parent",
cursor: "crosshair",
stop: function(ev, ui) {
scope.left=ui.helper[0].style.left;
scope.top=ui.helper[0].style.top;
}
});
}
};
<div ng-repeat="image in images"
draggable
ng-style="{left:image.left,
top:image.top}">... image stuff here ...</div>
Unfortunately, this doesn't work, because when ng-repeat creates the child scope for each image item, it
creates a new scope, which prototypically inherits from the parent scope, but it also assigns the item's value to a new property on the child scope. (The name of the new property is the loop variable's name.) (https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-repeat)
I can get the directive to work as I want it to by changing the reference to use the loop variable name:
scope.image.left=ui.helper[0].style.left;
scope.image.top=ui.helper[0].style.top;
but I don't want to hardcode the loop variable name into the directive.
What is the best way to pass the loop variable name to the directive or to, ideally, pass the reference to the item value to the directive directly?
Upvotes: 3
Views: 928
Reputation: 193261
In this case it is convenient to use isolated scope and pass current image object into directive using two-way binding.
So HTML can be something like this:
<div ng-repeat="image in images" draggable="image" ng-style="{left:image.left, top:image.top}">
<!-- ... image stuff here ... -->
</div>
and directive then:
.directive('draggable', function () {
return {
scope: {image: '=draggable'},
link: function (scope, element, attrs) {
element.draggable({
containment: "parent",
cursor: "crosshair",
stop: function (ev, ui) {
scope.image.left = ui.helper[0].style.left;
scope.image.top = ui.helper[0].style.top;
}
});
}
};
});
This way you no longer hardcode variable name and make directive more reusable. You can for example change HTML to ng-repeat="img in images" draggable="img"
but directive code will stay the same.
Upvotes: 2