2017-05-15 30 views
1

ノックアウトビューモデルに接続された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>

関連する問題