0

I have a table with rows. Each time I click a row, the viewmodel notifies it to other viewmodels by using a subscriber.

At the same time, I have icons on each row. Whenever I click on an icon I have a click binding to a function in one of my viewmodels.

Now, the problem arises when I try to get any value from the row in the click binded function.

It seems the subscription gets fired later than the click function. Therefore when I'm on the click function I can not access the data from the row yet.

I solved it by padding the row data directly in the click function. But then I want to be able to access the click function from outside the row, lets say, in a fixed or absolute element in my DOM, and therefore I won't be able to pass the row data from its click binding. That's why I'm using a subscriber that gets fired on row select.

My question is. How do we know when the subscriber is going to be fired? Is there any way to change the order?

self.sendDataAndClick = function(data){
    self.setData(data);

    self.showAddModal();
};

//gets the info from the orders vm
shouter.subscribe(function(data) {
    self.setData(data);
}, this, "selectedOrder");

//sets the data for the viewmodel
self.setData = function(data){
    self.equipmentNumber(data.equipment_id());
    self.leg(data);
    self.setSeals(data);
}
Alvaro
  • 40,778
  • 30
  • 164
  • 336
  • I've used the [`setTimeout(fn, 0)` construct](http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful) in situations like this before to ensure that a given subscription runs after all other updates have been done - may work for you too. – James Thorpe Oct 09 '15 at 11:05
  • I *think* you're looking at the icon click being processed before it bubbles to the row click. In any case, James' `setTimeout` suggestion is probably the way to go. – Roy J Oct 09 '15 at 12:10
  • You could use a ko extender, attach it to shouter, overwrite the `notifySubscribers` method to execute a callback after notification completes. – webketje Oct 09 '15 at 23:31

1 Answers1

0

Ok so here's my go at it. It might not fully answer your question, but it demonstrates how you can control the order of execution of subscriptions.

ko.extenders.queueSubs = function(target, value) {
    var sQueue = []; // subscription queue
    // set up a normal subscription and execute the queue subscriptions in order.
    target.subscribe(function(newValue) {
        sQueue.forEach(function(item, i) {
           sQueue[i](newValue);
        });
    });
    // overwrite the subscribe function of this observable into
    // a function that adds the subscription at a position in the queue
    target.subscribe = function(pos, fn) {
        sQueue.splice(pos, 0, fn);
    };
};
// use: ko.observable().extend({ queueSubs: true });
// queue a sub: ko.observable().subscribe(0, function(value) { alert(value); });

See an example here: http://jsfiddle.net/kevinvanlierde/6gsbghbb/

webketje
  • 10,376
  • 3
  • 25
  • 54