0

I'm sorting my ObservableArray in the markup thusly, but for some reason, when I push a new object to the pages ObservableArray, this does not update.

//store.get('pages') returns an ObservableArray

<!-- ko foreach:store.get('pages').sort(function (l , r ) { return l.pageNumber() < r.pageNumber() ? -1 : 1}) -->
    <markup/>
<!--/ko-->

However, when I remove the sort call, it catches the array change just fine. Like so,

//works fine,  updates when item pushed to observableArray
<!-- ko foreach:store.get('pages') -->
    <markup/>
<!--/ko-->

Any idea for a simple workaround?

Edits:

Tried using valueHasMutated(), doesn't force an update either.

Workaround: I ended up moving the sort call into a subscription on the observableArray, and it seems to be working fine now, not sure why though.

2
  • Have you tried putting that sort as a computed in your viewmodel? That sort of sort doesn't really belong in the view. Commented Sep 10, 2013 at 22:28
  • That didn't do it either, unfortunately. I did find a sort of end-run solution though, thanks! Commented Sep 10, 2013 at 22:41

1 Answer 1

1

store.get returns an observableArray but store.get(...).sort(...) returns an array. You're effectively making a one way binding like this:

<div data-bind="foreach: ['foo', 'bar']"></div>

Also, although you bind a returned value of a function call, to me it has a code smell that you're coupling your business logic with your view logic. You have something like this:

// View
<div data-bind="foreach: $root.get()"></div>

// Javascript
function ViewModel () {
    var self = this;
    self.get = function () {
        return ko.observableArray();
    };
}

And it works, but from your view, it's unclear what you're doing. I think a better solution would be:

// View
<div data-bind="foreach: stores"></div>

// Javascript
function ViewModel () {
    var self = this;
    self.stores = ko.observableArray();
    self.get = function () {
        var arr = ["foo", "bar"];
        stores(arr.sort(...));// When you do this, KO updates the foreach binding this is bound to
        return stores;// not that you need to, you can access it from the viewModel.
    };
}

Glad you found a workaround but take a minute and plan out your HTML binding structure. It's the first place I start when I'm creating a new view and it drives how I structure my ViewModel.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.