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
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.
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.
Try to call valueHasMutated
function after sorting:
dataTextsViewModel.texts.sort(textListOrderCompare);
dataTextsViewModel.texts.valueHasMutated();
dataTextsViewModel.texts(dataTextsViewModel.texts().sort(textListOrderCompare));
this way you change observable. Other way was changing the array inside and didn't trigger the change.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With