2012-04-21 11 views
20

Mam przycisk, który przenosi pozycję o jedną pozycję w lewo w obserwowalną tablicę. Robię to w następujący sposób. Jednak wadą jest to, że category() [index] zostaje usunięty z tablicy, odrzucając w ten sposób wszelkie manipulacje DOM (przez walidację jQuery w moim przypadku) w tym węźle.Jak zamienić dwa elementy na observableArray?

Czy istnieje sposób wymiany dwóch elementów bez użycia zmiennej tymczasowej, aby zachować węzeł DOM?

moveUp: function (category) { 
     var categories = viewModel.categories; 
     var length = categories().length; 
     var index = categories.indexOf(category); 
     var insertIndex = (index + length - 1) % length; 

     categories.splice(index, 1); 
     categories.splice(insertIndex, 0, category); 
     $categories.trigger("create"); 
    } 

Odpowiedz

36

Oto moja wersja moveUp że robi swap w jednym kroku:

moveUp: function(category) { 
    var i = categories.indexOf(category); 
    if (i >= 1) { 
     var array = categories(); 
     categories.splice(i-1, 2, array[i], array[i-1]); 
    } 
} 

To nadal nie rozwiązuje problemu , ponieważ Knockout nadal będzie widzieć swap jako usuwanie i dodawanie akcji. Jest jednak open issue dla Knockout do obsługi ruchomych przedmiotów. Aktualizacja: W wersji 2.2.0 Knockout rozpoznaje przeniesione elementy, a powiązanie foreach nie spowoduje ich ponownego renderowania.

+0

wielkie dzięki, tutaj jest ** moveDown ** przykład http: // stackoverflow.com/a/22348385/287084 – Orhaan

0

miałem podobny problem jak chciałem jQuery przeciągnij & kroplę na moich przedmiotów. Moim rozwiązaniem stało się użycie szablonów knockoutjs do wiązania zdarzeń beforeRemove i afterAdd z modelem. Funkcja Person Class/jest również prostym modelem widoku nokaut.

W poniższym przykładzie używam .draggable(), ale można łatwo użyć sprawdzania poprawności. Dodaj własny kod do manipulowania obserwowalną tablicą i powinieneś być dobry.

HTML:

<div data-bind="template: {foreach:attendeesToShow, beforeRemove:hideAttendee, afterAdd:showAttendee}"> 
    <div class="person"> 
     <img src="person.jpg" alt="" /> 
     <div data-bind="text: firstName" ></div> 
     <div class="deleteimg" data-bind="click:$parent.removeAttendee" title="Remove"></div> 
    </div> 
</div> 

ViewModel:

+0

Czy można opracować? Próbuję użyć przycisków, aby umożliwić użytkownikowi sortowanie (może zaimplementować przeciąganie i upuszczanie później). W jaki sposób obsługa beforeRemove, afterAdd zachowuje elementy DOM? Elementy DOM zostały wygenerowane przez Knockout, ale zostały zmienione przez walidację jQuery i tracę zmiany przez usunięcie i ponowne włożenie elementu. –

+0

W moim przykładzie po prostu ponownie dodaję przeciągalne, w procesie sprawdzania poprawności, kiedy element zostanie ponownie dodany do DOM. W moim przypadku nie trzeba zachowywać żadnych zmiennych stanu (wszystkie one są w modelu), więc to działa dla mnie. Czy zatwierdzanie nie powinno być takie samo? – jornare

0

dzięki Michael Best dla swojej wersji moveUp

moja wersja moveDown

moveDown: function(category) { 
    var array = categories(); 
    var i = categories.indexOf(category); 
    if (i < arr.length) { 
     categories.splice(i, 2, array[i + 1], array[i]); 
    } 
} 
+0

Twoja wersja nie działa poprawnie. Zastąpienie "arr.length" parametrem "array.length - 1". –

5

wiem ta odpowiedź przychodzi trochę późno, ale pomyślałem, że może to być przydatne dla innych, którzy chcą bardziej ogólnego rozwiązanie wymiany. Można dodać funkcję wymiany do observableArrays tak:

ko.observableArray.fn.swap = function(index1, index2) { 
    this.valueWillMutate(); 

    var temp = this()[index1]; 
    this()[index1] = this()[index2]; 
    this()[index2] = temp; 

    this.valueHasMutated(); 
} 

Następnie można użyć tej funkcji, aby zamienić dwa elementy w tablicy podane ich indeksach:

myArray.swap(index1, index2); 

Dla funkcji moveUp, można następnie wykonaj coś takiego:

moveUp: function(category) { 
    var i = categories.indexOf(category); 
    if (i > 0) { 
     categories.swap(i, i+1); 
    } 
} 
Powiązane problemy