I am new to Angular and have been trying to create a directive which will bind the position on an element to a model—after it has been dragged by the user. I found another Stack Overflow question which solves this for a simple object:
Angularjs directive attribute binding of left and top position after dragging
myApp.directive('draggable', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.draggable({
cursor: "move",
stop: function (event, ui) {
scope[attrs.xpos] = ui.position.left;
scope[attrs.ypos] = ui.position.top;
scope.$apply();
}
});
}
};
});
See Fiddle solution here: http://jsfiddle.net/mrajcok/5Mzda/
Now, I am now trying to get this to work with a more complex object and with ng-repeat
, but can't seem to figure out why it's not working.
Here is my HTML:
<div ng-controller="MyCtrl">
<div ng-repeat="position in positions">
<input type="number" ng-model="position.divleft"/>
<input type="number" ng-model="position.divtop"/>
<p draggable class="example" ng-style="{left: position.divleft, top: position.divtop}" xpos="position.divleft" ypos="position.divtop">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
And here is the JS:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.positions = [
{"divtop": 80,
"divleft": 200
},
{"divtop": 100,
"divleft": 250
}
];
};
myApp.directive('draggable', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.draggable({
cursor: "move",
stop: function (event, ui) {
scope[attrs.xpos] = ui.position.left;
scope[attrs.ypos] = ui.position.top;
scope.$apply();
}
});
}
};
});
Here is the Fiddle:
http://jsfiddle.net/5Mzda/19/
I can't seem to see what's wrong with the code. Would appreciate any help!
I read the comments more closely in original question, and it looks like using $eval
works:
myApp.directive('draggable', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.draggable({
cursor: "move",
stop: function (event, ui) {
scope.$eval(attrs.xpos + '=' + ui.position.left);
scope.$eval(attrs.ypos + '=' + ui.position.top);
scope.$apply();
}
});
}
};
});
Not sure if there's a more elegant way to do this, but it appears the binding is working properly now!
This looks fine.
You need execute all angular related expressions with in the angular framework. In case of dom event handlers and methods which are called from outside the event handlers, you need to execute them with in the angular using $apply, which will execute the expression and then call $digest which in turn will call the attached watches.
The only change you have to make is to move the statements inside $apply()
scope.$apply(function(){
scope.$eval(attrs.xpos + '=' + ui.position.left);
scope.$eval(attrs.ypos + '=' + ui.position.top);
});
Demo: Fiddle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With