2012-01-06 24 views
9

Tôi đang cố gắng tạo một mục danh sách có thể kéo trong một dự án đang sử dụng Knockout.js.Knockout & JQueryUI Drag - Điều gì khiến phần tử này không thể kéo được?

Tôi đang sử dụng mã dưới đây, và như bạn có thể nhìn thấy nó rất đơn giản:

<div id="room-view" > 
    <ul data-bind="foreach: rooms">      
     <li data-bind="text: name" class="draggable room-shape"></li>     
    </ul>    
</div> 

<script type="text/javascript"> 
    $(function() { 
     $(".draggable").draggable(); 
    }); 
</script> 

Danh sách các 'phòng' làm cho tốt, nhưng không ai trong số các mặt hàng đang kéo. Tuy nhiên, nếu tôi áp dụng lớp 'draggable' cho bất kỳ phần tử nào khác trên trang - nó sẽ trở thành có thể kéo được. Ngay cả khi chúng là các mục danh sách khác. Sự khác biệt duy nhất là các mục danh sách này đang được tạo thông qua ràng buộc 'foreach'.

Có ai có thể phát hiện ra điều gì có thể khiến chức năng này không hoạt động chính xác không?

Trả lời

23

foreach công trình bằng cách tiết kiệm ra một bản sao của các yếu tố để sử dụng như là "mẫu" bất cứ khi nào nó cần phải làm cho một mục. Vì vậy, các yếu tố mà bạn tạo ra có thể kéo được không phải là các yếu tố được hiển thị bởi foreach.

Bạn có thể thử đảm bảo rằng draggable được gọi sau applyBindings, nhưng điều đó sẽ chỉ có hiệu quả nếu rooms của bạn không phải là observableArray thay đổi. Bất kỳ mục mới nào được hiển thị sẽ không thể kéo được.

Tùy chọn khác là sử dụng tùy chọn afterRender để gọi draggable trên các yếu tố của bạn.

Cách tốt hơn là sử dụng liên kết tùy chỉnh. Nó có thể đơn giản như:

ko.bindingHandlers.draggable = { 
    init: function(element) { 
     $(element).draggable(); 
    } 
}; 

hoặc bạn có thể tiến vào một điều gì đó tốt hơn một chút nơi bạn thực sự cập nhật vị trí quan sát dựa trên vị trí các mục của bạn bị bỏ.

Tôi đã viết một bài viết một thời gian trở lại trên nó here. Với Knockout 2.0, tôi đã thực hiện một vài thay đổi để đơn giản hóa ràng buộc để bạn chỉ có thể sử dụng sortableList trên phụ huynh.

Đây là một mẫu chỉ có thể phân loại: http://jsfiddle.net/rniemeyer/DVRVQ/

Đây là một mẫu với thả giữa danh sách: http://jsfiddle.net/rniemeyer/sBHaP/

+0

Ahhh, sự sụt giảm giữa các danh sách mẫu là tuyệt vời - chính xác những gì tôi đang tìm kiếm. Cảm ơn bạn! – PhillipKregg

+0

Điều này thật đáng kinh ngạc nhưng vẫn có rất nhiều quyền kiểm soát. Cảm ơn bạn! – Nek

+1

+1 cho ví dụ jsfiddle – Pieter

7

Sự cố là draggable() được áp dụng khi tài liệu sẵn sàng trên thành phần hiện tại. Knockout.js sẽ sửa đổi HTML và tạo các phần tử mới ngay từ đầu và cũng khi mảng rooms được cập nhật.

Điều bạn cần là cho phép kéo mỗi lần xuất hiện room-view. Bạn có thể sử dụng afterRender cho điều đó.

Hãy thử điều này:

<div id="room-view" > 
    <ul data-bind="foreach: { data: rooms, afterRender: afterRender }">      
    <li data-bind="text: name" class="draggable room-shape"></li>     
    </ul>    
</div> 

<script type="text/javascript"> 
    // this is your already existing view-model that contains rooms, etc 
    function roomsViewModel() { 
    // ... 

    // insert this in your view-model 
    this.afterRender = function() { 
     $(".draggable").draggable(); 
    } 
    } 

    ko.applyBindings(new roomsViewModel()); 
</script> 
+0

câu trả lời của bạn cũng là cực kỳ hữu ích - Tôi ước gì có thể đánh dấu 2 câu trả lời. – PhillipKregg

+1

@PhillipKregg Hehe, cảm ơn bạn :). Câu trả lời của Ryan là tuyệt vời và anh ấy là một người nổi tiếng Knockout.js, vì vậy anh ấy xứng đáng là người nổi tiếng: P. – kubetz

+0

@dzejkej câu trả lời hay quá! –

Các vấn đề liên quan