2017-03-17 67 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

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

邁克爾,這是真正有用的,先生。我認爲我正確實現了你的想法,但由於某種原因我得到這個錯誤: 錯誤:Uncaught ReferenceError:無法處理綁定「foreach:function(){return randomize(docs)}」消息:randomize未定義 –

+0

對於'randomize'在綁定中可用,它應該是全局函數('window.randomize = ...')或視圖模型。 –

+0

有道理!星期一我會出手。再次感謝邁克爾! –

0

一些問題:首先你要使用自定義在foreach結合內結合。您可以在同一個HTML元素中使用多個綁定,但它們應該用逗號分隔。

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

定製結合「初始化」的方法具有提供一種方式來訪問在其它綁定正在使用的相同元件視圖模型的屬性的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

Rafael,感謝您的幫助,我相信它會起作用!我實現了這一點,但由於某種原因它沒有任何影響。沒有任何錯誤。 –