Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.js ObservableArray sort not updating UI

I have a Knockout observable array that refuses to update the UI (a jquery Accordion) to which it is bound after a .sort() call, but happily updates the UI after a .reverse() call - I've been banging my head against this problem for days - can't seem to find an answer... help!

Container View Model - implements the observableArray Property :

function DataTextsKOViewModel( jsonTexts  ) {
    var self = this;

    // Texts array 
    self.texts = ko.observableArray();

    // Build from json data array 
    for (var i = 0; i < jsonTexts.AuthorityTexts.length; i++) {
        var jsontext = jsonTexts.AuthorityTexts[i];
        // Push Text VModel objects onto the KO observable array list ..
        self.texts.push(
                new DataTextKOViewModel( jsontext )
           );
    }

}

Array Object Model - These are the objects which are sorted:

// Single data text view model
function DataTextKOViewModel(jsonText) {
    // Other properties omitted for brevity 
    this.ListOrder = ko.observable(jsonText.ListOrder);
}

Custom Sort Function :

function textListOrderCompare(l, r) {

// Ascending sort
var retval = ((l.ListOrder() == r.ListOrder()) ? 0 
: ((l.ListOrder() > r.ListOrder()) ? 1 : -1));

return retval;
}

Binding Markup :

<!-- ko foreach: texts -->    
<div class="group" data-bind="attr:{'id': clientId() }">   
     <h3 data-bind="attr:{'dataKey': responsibilityId() }">
        <span data-bind="text: responsibilitySectionHeader"></span>
     </h3>    
     <div>
        <!-- section content goes here -->
     </div>
</div>  

When User Elects to sort:

myDataTextsKOViewModel.rollbackChanges();
dataTextsViewModel.texts.sort(textListOrderCompare);  
// UI Never updates - but I've checked console output to ensure that the array 
/ /sorts correctly

dataTextsViewModel.texts.sort(textListOrderCompare);  
// UI updates with items in reverse order 

Any help you can give me would be most appreciated.

EDIT: Should have mentioned - I already call valueHasMutated() on the observable array property after the .sort()! - Andrew

like image 240
andrewe Avatar asked Nov 11 '13 13:11

andrewe


People also ask

What is ko observableArray?

Behind the scenes, an observableArray is actually an observable whose value is an array (plus, observableArray adds some additional features described below). So, you can get the underlying JavaScript array by invoking the observableArray as a function with no parameters, just like any other observable.

How do you activate a Knockoutjs model?

Activating Knockout To activate Knockout, add the following line to a <script> block: ko. applyBindings(myViewModel); You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as jQuery's $ function.


2 Answers

Try to call valueHasMutated function after sorting:

dataTextsViewModel.texts.sort(textListOrderCompare); 
dataTextsViewModel.texts.valueHasMutated();
like image 168
Artem Vyshniakov Avatar answered Oct 24 '22 03:10

Artem Vyshniakov


dataTextsViewModel.texts(dataTextsViewModel.texts().sort(textListOrderCompare));

this way you change observable. Other way was changing the array inside and didn't trigger the change.

like image 1
Dominictus Avatar answered Oct 24 '22 03:10

Dominictus