Arrastrar y soltar Ng Ng: ¿se repite en AngularJS?
-
28-10-2019 - |
Pregunta
¿Es fácil de usar? jQuery.sortable
en ng-repeat
elementos en angularjs?
Sería increíble si el reordenamiento de los elementos se propagó automáticamente ese pedido de nuevo en la matriz de origen. Sin embargo, me temo que los dos sistemas pelearían. ¿Hay una mejor manera de hacer esto?
Solución
Angular UI tiene una directiva ordenable,Haga clic aquí para la demostración
Código ubicado en fundamental, uso:
<ul ui-sortable ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
Otros consejos
Traté de hacer lo mismo y se me ocurrió la siguiente solución:
angular.directive("my:sortable", function(expression, compiledElement){
return function(linkElement){
var scope = this;
linkElement.sortable(
{
placeholder: "ui-state-highlight",
opacity: 0.8,
update: function(event, ui) {
var model = scope.$tryEval(expression);
var newModel = [];
var items = [];
linkElement.children().each(function() {
var item = $(this);
// get old item index
var oldIndex = item.attr("ng:repeat-index");
if(oldIndex) {
// new model in new order
newModel.push(model[oldIndex]);
// items in original order
items[oldIndex] = item;
// and remove
item.detach();
}
});
// restore original dom order, so angular does not get confused
linkElement.append.apply(linkElement,items);
// clear old list
model.length = 0;
// add elements in new order
model.push.apply(model, newModel);
// presto
scope.$eval();
// Notify event handler
var onSortExpression = linkElement.attr("my:onsort");
if(onSortExpression) {
scope.$tryEval(onSortExpression, linkElement);
}
}
});
};
});
Usado así:
<ol id="todoList" my:sortable="todos" my:onsort="onSort()">
Parece funcionar bastante bien. El truco es deshacer la manipulación DOM realizada por SAPTABLE antes de actualizar el modelo, de lo contrario, Agular se desincroniza del DOM.
La notificación de los cambios funciona a través de la expresión my: onsort que puede llamar a los métodos del controlador.
Creé un jsfiddle basado en el tutorial Angular TODO para mostrar cómo funciona: http://jsfiddle.net/m8ynr/180/
Así es como lo estoy haciendo con Angular V0.10.6. Aquí está el jsfiddle
angular.directive("my:sortable", function(expression, compiledElement){
// add my:sortable-index to children so we know the index in the model
compiledElement.children().attr("my:sortable-index","{{$index}}");
return function(linkElement){
var scope = this;
linkElement.sortable({
placeholder: "placeholder",
opacity: 0.8,
axis: "y",
update: function(event, ui) {
// get model
var model = scope.$apply(expression);
// remember its length
var modelLength = model.length;
// rember html nodes
var items = [];
// loop through items in new order
linkElement.children().each(function(index) {
var item = $(this);
// get old item index
var oldIndex = parseInt(item.attr("my:sortable-index"), 10);
// add item to the end of model
model.push(model[oldIndex]);
if(item.attr("my:sortable-index")) {
// items in original order to restore dom
items[oldIndex] = item;
// and remove item from dom
item.detach();
}
});
model.splice(0, modelLength);
// restore original dom order, so angular does not get confused
linkElement.append.apply(linkElement,items);
// notify angular of the change
scope.$digest();
}
});
};
});
Aquí está mi implementación de la directiva de Orgular.js Sortable sin jQuery.ui:
Puede optar por la directiva Ng-sortable que es liviana y no usa jQuery. Aquí está el enlace Elementos de arrastre y caída de arrastre de Ng