2017-03-17 24 views
1

foreach順序付きリストを取得し、リスト項目をランダムにシャッフルしようとしています。私は関数(randomOrder)を作成し、これをforeach項目のバインディングに使用しました。 何も動作していないようです。Knockout.js内のForeachリスト項目をランダム化

HTML:

<ol data-bind="foreach: { data: docs, randomOrder: true} "> 
    <li class="result" data-bind="component: { name: 'physicianreferral.docresult', params: { doc: $data } }"></li> 
</ol> 

JS:

ko.bindingHandlers.randomOrder = { 
     init: function (elem, valueAccessor) { 
      // Build an array of child elements 
      var child = ko.virtualElements.firstChild(elem), 
       childElems = []; 
      while (child) { 
       childElems.push(child); 
       child = ko.virtualElements.nextSibling(child); 
      } 

      // Remove them all, then put them back in a random order 
      ko.virtualElements.emptyNode(elem); 
      while (childElems.length) { 
       var randomIndex = Math.floor(Math.random() * childElems.length), 
        chosenChild = childElems.splice(randomIndex, 1); 
       ko.virtualElements.prepend(elem, chosenChild[0]); 
      } 
     } 
    }; 
    ko.virtualElements.allowedBindings.randomOrder = true; 

答えて

2

まず、あなたの結合foreachの一部ではないので、トップレベルで指定する必要があります:

foreach: docs, randomOrder: true 

しかし、私はこの方法をまったく使用しないことをお勧めします。

foreach: randomize(docs) 

JS:

function randomize(arr) { 
    var newArray = []; 
    while (arr.length) { 
     var randomIndex = Math.floor(Math.random() * arr.length); 
     newArray.push(arr.splice(randomIndex, 1)[0]); 
    } 
    return newArray; 
}; 
+0

マイケルは、これは先生、本当に便利です。 エラー:キャッチされていないReferenceError:バインディングを処理できません "メッセージを返す:{return randomize(docs)}"メッセージ:ランダム化が定義されていません。 –

+0

バインディングで 'randomize'を利用できるようにするには、グローバル関数(' window.randomize = ... ')かビューモデルでなければなりません。 –

+0

意味があります!私は月曜日にそれを打ち明けます。もう一度ありがとう、マイケル! –

0

いくつかの問題:最初にあなたが結合foreachの中にカスタムバインディングを使用しようとしているだけで、あなたがforeachに渡す配列をランダム。同じHTML要素で複数のバインディングを使用できますが、コンマで区切る必要があります。

<ol data-bind="foreach: { data: docs }, randomOrder: true"> 

カスタム結合「のinit」メソッドは、同じ要素の他のバインディングで使用されているビューモデルのプロパティにアクセスする方法を提供allBindingAccessorを有しています。

var array = allBindingsAccessor().foreach.data(); 

使用可能な配列では、任意のアルゴリズムを使用してシャッフルできます。私はスニペットにFisher-Yates(別名Knuth)Shuffleを追加しました。これはanswerから直接コピーされました。毎回シャッフルされていることを確認するには、[コードスニペットを実行する]をクリックします。

ko.bindingHandlers.randomOrder = { 
 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
 
     var array = allBindingsAccessor().foreach.data(); 
 

 
     var currentIndex = array.length, temporaryValue, randomIndex; 
 

 
     // while there remain elements to shuffle... 
 
     while (0 !== currentIndex) { 
 

 
      // Pick a remaining element... 
 
      randomIndex = Math.floor(Math.random() * currentIndex); 
 
      currentIndex -= 1; 
 

 
      // And swap it with the current element. 
 
      temporaryValue = array[currentIndex]; 
 
      array[currentIndex] = array[randomIndex]; 
 
      array[randomIndex] = temporaryValue; 
 
     } 
 

 
     allBindingsAccessor().foreach.data(array); 
 
    } 
 
}; 
 

 
var ViewModel = function() { 
 
    var self = this; 
 

 
    self.docs = ko.observableArray([1, 2, 3, 4, 5, 6, 7, 8 ,9, 10]); 
 
}; 
 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 
 

 
<ol data-bind="foreach: { data: docs }, randomOrder: true"> 
 
    <li data-bind="text: $data"></li> 
 
</ol>

+0

ラファエル、助けてくれてありがとう!私はこれを実装しましたが、何らかの理由で影響がありません。エラーもありません。 –

関連する問題