2012-04-21 23 views
20

Tôi có một nút di chuyển một mục ở vị trí còn lại trong một ObservableArray. Tôi đang làm theo cách sau. Tuy nhiên, nhược điểm là các loại() [index] bị loại bỏ khỏi mảng, do đó loại bỏ bất kỳ thao tác DOM nào (bằng cách xác thực jQuery trong trường hợp của tôi) trên nút đó.Làm cách nào để trao đổi hai mục trong một ObservableArray?

Có cách nào để hoán đổi hai mục mà không sử dụng biến tạm thời để giữ nguyên nút DOM không?

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"); 
    } 

Trả lời

36

Dưới đây là phiên bản của tôi về moveUp mà không được trao đổi trong một bước:

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

Điều đó vẫn không giải quyết được vấn đề , mặc dù, bởi vì Knockout sẽ vẫn thấy trao đổi là xóa và thêm hành động. Tuy nhiên, có open issue để Knockout hỗ trợ các mục di chuyển. Cập nhật: Kể từ phiên bản 2.2.0, Knockout không nhận ra các mục đã di chuyển và liên kết foreach sẽ không hiển thị lại chúng.

+0

cảm ơn rất nhiều, đây là ví dụ ** moveDown ** ví dụ http: // stackoverflow.com/a/22348385/287084 – Orhaan

0

Tôi gặp vấn đề tương tự như khi tôi muốn jQuery kéo các mục của mình vào mục &. Giải pháp của tôi đã trở thành sử dụng các mẫu knockoutjs để ràng buộc beforeRemove và sauThêm sự kiện vào mô hình. Lớp Person/chức năng cũng là một mô hình xem loại trực tiếp đơn giản.

Trong ví dụ dưới đây, tôi sử dụng .draggable(), nhưng bạn có thể dễ dàng sử dụng xác thực. Thêm mã của riêng bạn để thao tác với ObservableArray và bạn nên làm tốt.

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

Có thể xây dựng? Những gì tôi đang cố gắng làm là sử dụng các nút để cho phép người dùng sắp xếp (có thể triển khai kéo và thả sau). Cách xử lý beforeRemove, afterAdd giữ nguyên các phần tử DOM? Các phần tử DOM được tạo ra bởi Knockout, nhưng đã được thay đổi bằng xác thực jQuery và tôi mất các thay đổi bằng cách loại bỏ sau đó chèn lại mục đó. –

+0

Trong ví dụ của tôi, tôi chỉ cần thêm lại kéo, trong trường hợp xác thực của bạn, khi mục được thêm lại vào DOM. Trong trường hợp của tôi, nó không cần phải bảo tồn bất kỳ biến trạng thái nào (chúng đều nằm trong mô hình) để nó hoạt động cho tôi. Không nên xác nhận cũng giống nhau không? – jornare

0

nhờ Michael Best cho phiên bản của ông moveup

phiên bản của tôi về 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

Phiên bản của bạn không hoạt động chính xác. Thay thế "arr.length" bằng "array.length - 1" thực hiện thủ thuật. –

5

Tôi biết câu trả lời này đến hơi muộn, nhưng tôi nghĩ rằng nó có thể có ích cho những người muốn có một tổng quát hơn trao đổi giải pháp. Bạn có thể thêm một chức năng hoán đổi để observableArrays bạn như vậy:

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

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

    this.valueHasMutated(); 
} 

Sau đó bạn có thể sử dụng chức năng này để trao đổi hai yếu tố trong một mảng cho chỉ số của họ:

myArray.swap(index1, index2); 

Đối với một hàm moveUp, bạn có thể sau đó làm điều gì đó như sau:

moveUp: function(category) { 
    var i = categories.indexOf(category); 
    if (i > 0) { 
     categories.swap(i, i+1); 
    } 
} 
Các vấn đề liên quan