2017-05-15 5 views
1

나는 Knockout viewmodel에 연결된 html 뷰를 가지며 항목 목록을 표시합니다. 목록의 각 항목에는 텍스트 이름 필드와 숫자 주문 필드가 있습니다. 사용자는 UL 목록의 항목에 "끌어서 놓기"작업을 수행 할 수 있습니다.항목의 순서를 나타내는 배열의 녹아웃 관측 가능 필드

<div id="wrapper"> 
<ul data-bind="foreach:Items"> 
    <li draggable="true" 
     ondragover="event.preventDefault();" 
     data-bind="event:{dragstart:$root.dragItem,drop:$root.dropItem}"> 
     <label data-bind="text:name"></label> 
     <label data-bind="text:orderNo"></label> 
     <input type="text" data-bind="value:name" /> 
    </li> 
</ul> 

<script type="text/javascript"> 
var list = [{ name: 'Red', orderNo: 0 } 
    , { name: 'Green', orderNo: 1 } 
    , { name: 'Blue', orderNo: 2 }]; 
function viewmodel() { 
    var self = this; 
    self.Items = ko.mapping.fromJS(list); 

    self.ItemToDrag = ko.observable(); 
    self.dragItem = function (item, event) { 
     self.ItemToDrag(item); 
     return true; 
    } 
    self.dropItem = function (item, event) { 
     event.preventDefault(); 
     var up = self.ItemToDrag().orderNo() > item.orderNo(); 
     self.ItemToDrag().orderNo(up ? item.orderNo() - 0.5 : item.orderNo() + 0.5); 
     //order this list 
     self.Items.sort(function (left, right) { 
      return left.orderNo() == right.orderNo() ? 0 : (left.orderNo() < right.orderNo() ? -1 : 1); 
     }); 
     //set integer number 
     for (var i = 0; i < self.Items().length; i++) { 
      self.Items()[i].orderNo(i); 
     } 
    } 
} 


var vm; 
$(document).ready(function() { 
    vm = new viewmodel(); 
    ko.applyBindings(vm, $("#wrapper")[0]); 
}); 

내 질문은, 자동 주문 필드의 내용을 변경하는 녹아웃으로 가능하다면 다음과 같이 은 "드래그 앤 드롭"이벤트는 항목의 순서를 변경 목록의 항목이 UI를 통해 주문을 변경하면 어떤 필드 ORDERKEY이 항목의 순서를 나타냅니다

<ul data-bind="foreach:Items,orderKey:orderNo"></ul> 

같은 뭔가 및 순서 변경의 경우 업데이트합니다.

답변

0

저는 이것이 정확히 필요한지 확신하지 못합니다. 이 전에 바인딩 foreach에서 배열을 정렬하는 사용자 정의 바인딩입니다 :

ko.bindingHandlers.foreach["after"] = ["orderKey"]; 
 
    ko.bindingHandlers.orderKey = { 
 
\t  update: function (el, valueAccessor, allBindingsAccessor, viewModel) { 
 
\t   var key = ko.unwrap(valueAccessor()); 
 
\t   var allBindings = allBindingsAccessor(); 
 
\t   if("foreach" in allBindings) { 
 
\t    var array = ko.unwrap(allBindings.foreach); 
 
\t    array.sort(function(a, b) { return a[key] > b[key]; }); 
 
\t    allBindings.foreach = array; 
 
\t   }      
 
\t  } 
 
\t }; 
 
    
 
    // The model 
 
    var model = { Items: ko.observableArray([{text: 3}, {text: 1}, {text: 2}]) }; 
 
    // Apply 
 
    ko.applyBindings(model); 
 

 
    // This simulate changes in observableArray 
 
    setTimeout(function() { model.Items.push({text: 0}) }, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script> 
 

 
<ul data-bind="foreach: Items, orderKey: 'text'"> 
 
    <li data-bind="text: text"></li> 
 
</ul>

0

아니, 사용 사례에 대한 바인딩 특정이 없습니다. 그러나 녹아웃에서는 맞춤 바인딩을 작성하는 것이 간단합니다. the documentation을 참조하십시오. 내가 일하고있는 회사에서 우리는 커다란 사용자 정의 바인딩이있는 녹아웃 기반 프레임 워크 (우리가 개발)를 사용하고 있으며, 그 중 일부는 실제로 복잡합니다.

유스 케이스에 대한 바인딩을 만들기 시작했습니다. 그러나 당신이 그런 목록을 가지고 있지 않다면 그 목적에 부합하지 않을 것이라는 것을 깨달았습니다.

그러나 할 수있는 일은 실제 정렬을 knockout computed에 넣고 드롭 기능에서 정렬 색인을 업데이트하는 것입니다. 아래 예를 참조하고 명확하지 않은지 물어 보는 것을 주저하지 마십시오.

var list = [{ name: 'Red', orderNo: 0 } 
 
    , { name: 'Green', orderNo: 1 } 
 
    , { name: 'Blue', orderNo: 2 }]; 
 
    
 
function viewmodel() { 
 
    var self = this; 
 
    self._items = ko.mapping.fromJS(list); 
 
    self.Items = ko.pureComputed(function() { 
 
    \t return self._items().sort(function (a, b) { 
 
     \t return a.orderNo() < b.orderNo() ? -1 : 1; 
 
     }); 
 
    }); 
 

 
    self.ItemToDrag = ko.observable(); 
 
    self.dragItem = function (item, event) { 
 
     self.ItemToDrag(item); 
 
     return true; 
 
    } 
 
    self.dropItem = function (item, event) { 
 
     event.preventDefault(); 
 
     var up = self.ItemToDrag().orderNo() > item.orderNo(); 
 
     self.ItemToDrag().orderNo(up ? item.orderNo() - 0.5 : item.orderNo() + 0.5); 
 
    } 
 
} 
 

 

 
var vm; 
 
$(document).ready(function() { 
 
    vm = new viewmodel(); 
 
    ko.applyBindings(vm, $("#wrapper")[0]); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script> 
 

 
<div id="wrapper"> 
 
<ul data-bind="foreach:Items"> 
 
    <li draggable="true" 
 
     ondragover="event.preventDefault();" 
 
     data-bind="event:{dragstart:$root.dragItem,drop:$root.dropItem}"> 
 
     <label data-bind="text:name"></label> 
 
     <label data-bind="text:orderNo"></label> 
 
     <input type="text" data-bind="value:name" /> 
 
    </li> 
 
</ul>