javascript - modulos - AngularJS: directiva que actualiza el alcance principal dentro de ng-repeat
ng-model (1)
Tengo una directiva personalizada que se puede arrastrar dentro de una repetición ng de imágenes. Quiero almacenar el desplazamiento x, y de cada imagen después de haber sido arrastrado. Por lo tanto, necesito la directiva para actualizar un campo en la imagen.
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>
Lamentablemente, esto no funciona, porque cuando ng-repeat crea el ámbito hijo para cada elemento de imagen,
crea un nuevo ámbito, que prototípicamente hereda del ámbito primario, pero también asigna el valor del elemento a una nueva propiedad en el ámbito secundario. (El nombre de la nueva propiedad es el nombre de la variable de bucle) ( https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-repeat )
Puedo hacer que la directiva funcione como yo quiero al cambiar la referencia para usar el nombre de la variable de bucle:
scope.image.left=ui.helper[0].style.left;
scope.image.top=ui.helper[0].style.top;
pero no quiero codificar el nombre de la variable de bucle en la directiva.
¿Cuál es la mejor manera de pasar el nombre de la variable de bucle a la directiva o, idealmente, pasar directamente la referencia al valor del elemento a la directiva?
En este caso, es conveniente utilizar un alcance aislado y pasar el objeto de imagen actual a la directiva mediante el enlace bidireccional.
Entonces HTML puede ser algo como esto:
<div ng-repeat="image in images" draggable="image" ng-style="{left:image.left, top:image.top}">
<!-- ... image stuff here ... -->
</div>
y directiva entonces:
.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;
}
});
}
};
});
De esta forma ya no codificará el nombre de la variable y hará que la directiva sea más reutilizable. Por ejemplo, puede cambiar HTML a ng-repeat="img in images" draggable="img"
pero el código de la directiva permanecerá igual.