rniemeyer / knockout-postbox

A small library that uses Knockout's native pub/sub capabilities to facilitate decoupled communication between separate view models or components.
MIT License
350 stars 55 forks source link

Enhanced context information for .publishOn / .subscribeTo #7

Closed fbuchinger closed 12 years ago

fbuchinger commented 12 years ago

In my app I've modelled a web form as a hierarchic structure of fields, groupds and the form. When I change the visibility of a group, all contained fields should also be invisible (same goes for editibility). As I want a loose coupling between my sub-models, I decided to use PubSub/ko.postbox.

But my problem is that the publishOn / 'subscribeTo' methods are lacking context information for this task. subscribeTo just gives me the newValue of the "observed observable", but not its id or other properties. I need this information e.g. to determine if a field is contained in a hidden group.

Sure I could add the identifier (name) of the property to the channel name, but I want to avoid this, so that I can subscribe to the group:visibility:change event in general (e.g. perform an action every time the visibility of the group changes)

Any idea how i could enhance the event handler context with the needed info?


function FieldModel (name, value, isVisible){
    this.isVisible =  = ko.observable(isVisible).subscribeTo('group:visibility:change', function (new Value){
         //only change the visibility of field if it is a child of the group
        // but missing context information (groupid etc)
    }) ;
   this.name = name;
   this.value = ko.observable(value);
}

function GroupModel (name, isVisible, childFields){
    this.isVisible = ko.observable(isVisible).publishOn('group:visibility:change');
    this.name = name;
    this.childFields = childFields;
}

function FormModel (name, childGroups) {
   this.name = name;
   this.childGroupd = childGroups;
}

var fieldA = new FieldModel('fieldA', 'some value', false);
var fieldB = new FieldModel('fieldB', 'some value', false);

var groupA = new GroupModel('groupA', true, [fieldA]);
var groupB = new GroupModel('groupB', true, [fieldB]);

myform = new FormModel ('test', [groupA, groupB]);
rniemeyer commented 12 years ago

@fbuchinger Sorry to not get back to your earlier on this one. I suppose that one option would be to put your publishOn onto a computed that actually returns an object that has the value along with the extra context. Then, in your subscribeTo, you could specify a transform to look at the context and determine the final boolean. Does that make sense?

fbuchinger commented 12 years ago

thanks for this interesting approach... Could you give a tiny example? I thought subscribeTo just receives the "naked" value, not the observable/computed itself.

fbuchinger commented 12 years ago

After playing around a bit, I managed to figure it out on my own! Many thanks for your advice!

rniemeyer commented 12 years ago

@fbuchinger ok- great. Sorry that I hadn't had a chance to respond. Let me know if you have more issues/questions.