Giter Site home page Giter Site logo

rniemeyer / knockout-postbox Goto Github PK

View Code? Open in Web Editor NEW
350.0 23.0 55.0 241 KB

A small library that uses Knockout's native pub/sub capabilities to facilitate decoupled communication between separate view models or components.

License: MIT License

JavaScript 98.85% HTML 1.15%

knockout-postbox's Introduction

knockout-postbox

knockout-postbox is a Knockout.js plugin designed to use Knockout's basic pub/sub capabilities to facilitate decoupled communication between separate view models / components.

More background here: http://www.knockmeout.net/2012/05/using-ko-native-pubsub.html

This allows you to set up simple topic-based communication like:

var ViewModelOne = function() {
  //automatically update the observable's value from ko.postbox messages on "myEditableTopic"
  this.isEditable = ko.observable().subscribeTo("myEditableTopic");  
};

var ViewModelTwo = function() {
  //automatically publish changes through ko.postbox using "myEditableTopic" as the topic
  this.editable = ko.observable(false).publishOn("myEditableTopic");  
};

var ViewModelThree = function() {
  //both subscribe to and publish changes on the topic "myEditableTopic"
  this.canEdit = ko.observable().syncWith("myEditableTopic");
};

//a non-KO component can also participate in this communication
var SomeOtherComponent = function() {
  //subscribe directly to the topic
  var subscription = ko.postbox.subscribe("myEditableTopic", function(newValue) {
     //do something with newValue
  }); 
  
  //in a disposal function, can call subscription.dispose();
  
  //publish on the topic
  ko.postbox.publish("myEditableTopic", "some new value");
};

The subscriptions do not need to be created when the observables are instantiated. You could just as easily wire it up later, if you don't want the individual view models to know that they are participating in this communication.

var ViewModelOne = function() {
  this.isEditable = ko.observable();  
};

var ViewModelTwo = function() {
  this.editable = ko.observable(false);  
};

var one = new ViewModelOne();
var two = new ViewModelTwo();

var editableTopic = "myEditableTopic";
one.isEditable.subscribeTo(editableTopic);
two.editable.publishOn(editableTopic)

The observable extensions accept additional arguments that can help to customize the sending/receiving behavior, as described below.

Basic Usage

knockout-postbox creates a ko.postbox object that can be used for basic pub/sub communication. However, typically you would use the observable extensions rather than calling the ko.postbox APIs directly, unless you are integrating with a non-KO component.

subscribe - ko.postbox.subscribe(topic, handler, [target], [initializeWithLatestValue])

var subscription = ko.postbox.subscribe("mytopic", function(newValue) {
    console.log("Value: " + newValue);
}, viewModel);

//receive updates from "mytopic", initialize with latest published value
var subscription = ko.postbox.subscribe("mytopic", function(newValue) {
    console.log("Value: " + newValue);
}, viewModel, true);

//in a disposal function, can call subscription.dispose() to clean-up the subscription
cleanup() {
    subscription.dispose();
}

publish - ko.postbox.publish(topic, value)

ko.postbox.publish("mytopic", "new value");

ko.postbox.defaultComparer

The default comparison done to determine if a value should be published simply uses ===. At run-time you can supply your own default comparison function by overriding ko.postbox.defaultComparer.

ko.postbox.reset

This function disposes all subscriptions related to ko.postbox and clears any stored references to those subscriptions.

Observable Extensions

knockout-postbox augments observables, observableArrays, and computed observables to be able to automatically participate in sending and receiving messages through ko.postbox.

subscribeTo - subscribeTo(topic, [initializeWithLatestValue], [transform])

The subscribeTo function tells an observable to automatically update itself whenever it receives a message on a topic.

//update the value from messages on "mytopic"
this.value = ko.observable().subscribeTo("mytopic");

//receive updates from "mytopic" and use the last published value to initialize the observable
this.value = ko.observable().subscribeTo("mytopic", true);

//receive updates from "mytopic" and update the value after passing it through the transform function
var transform = function(newValue) {
    return newValue && newValue.toLowerCase();
};

this.value = ko.observable().subscribeTo("mytopic", transform);

//receive updates from "mytopic", initialize with latest published value, and send updates through transform
this.value = ko.observable().subscribeTo("mytopic", true, transform);

unsubscribeFrom - unsubscribeFrom(topic)

The unsubscribeFrom function removes the subscription that an observable has on a topic.

this.value.unsubscribeFrom("mytopic");

publishOn - publishOn(topic, [skipInitialPublish], [equalityComparer])

The publishOn function tells an observable to automatically publish its value on a topic whenever it changes. By default, it will only publish when the new value is not the same (===) as the previous value.

//whenever the value changes publish a message on "mytopic"
this.value = ko.observable(value).publishOn("mytopic");

//publish changes on "mytopic", but skip publishing the current value immediately
this.value = ko.observable(value).publishOn("mytopic", true);

//publish changes on "mytopic" when the comparer function returns false
var comparer = function(newValue, oldValue) {
    return newValue < oldValue;
};

this.value = ko.observable(value).publishOn("mytopic", comparer);

//publish changes on "mytopic", skip initial publish, and use override comparer
this.value = ko.observable(value).publishOn("mytopic", true, comparer);

stopPublishingOn - stopPublishingOn(topic)

The stopPublishingOn function removes the subscription used to automatically publish changes to the observable.

this.value.stopPublishingOn("mytopic");

syncWith - syncWith(topic, [initializeWithLatestValue], [skipInitialPublish], [equalityComparer])

The syncWith function tells an observable to both subscribe and publish on a topic. This allows observables in two different view models to stay in sync with each other without having direct knowledge of its counterpart.

//subscribe to and publish on a topic
this.value = ko.observable(value).syncWith("mytopic");

//subscribe to and publish on a topic and use the last published value to initialize the observable
this.value = ko.observable().syncWith("mytopic", true);

//subscribe to and publish on a topic, but do not publish out the observable's value initially
this.value = ko.observable(value).syncWith("mytopic", false, true);

//subscribe to and publish on a topic, but only publish when the comparer function returns false
var comparer = function(newValue, oldValue) {
    return newValue < oldValue;
};

this.value = ko.observable(value).syncWith("mytopic", false, false, comparer);

stopSyncingWith - stopSyncingWith(topic)

The stopSyncingWith function removes the subscription that an observable has on a topic as well as the subscription used to automatically publish changes to the observable.

this.value.stopSyncingWith("mytopic");

dispose - dispose()

The dispose function removes all the subscriptions that an observable has on any topic as well as all the subscriptions used to automatically publish changes to the observable.

This function is attached to the observable when publishOn, subscribeTo or syncWith is called. If the observable already has a pre-existing dispose function, then it is automatically called in addition to performing the clean-up steps mentioned above.

this.value.dispose();

Dependencies

  • Knockout 2.0+
  • JSON2.js - (for IE < 8)

Build

This project uses grunt for building/minifying.

Install from NuGet

Install-Package Knockout-Postbox

Install from Bower

bower install knockout-postbox

Examples

The examples directory contains a sample that shows how three independent view models can exchange information without direct references to each other.

View the sample in jsFiddle here: http://jsfiddle.net/rniemeyer/mg3hj/

License

MIT http://www.opensource.org/licenses/mit-license.php

knockout-postbox's People

Contributors

ameng avatar gkubisa avatar riltsken avatar rniemeyer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

knockout-postbox's Issues

Support for "Always Publish" option

I've encountered a few scenarios where I'd like a value to be published always, regardless of whether the value has changed. Currently I'd have to take the following approach:

ko.observable().publishOn("topic", function() {return false;});

Which is perfectly serviceable, but it would be nice if there was a shorthand way of signalling the always-publish intention, rather than having to write out a function each time. I can't see a good place where this could be hooked into the source, but I expect you'd have a better idea than me on this matter!

Execution time, serialization, large data and topicCache

Large amount of data (100+kb) increases execution time up to 185x +
Perhaps there is a need for serialized variable configuration, like:

exports.serializer = ko.toJSON // by default

but if i work only with js-like data, i can do:

postbox.serializer = JSON.stringify
// ko.subscribable.fn.toJSON = function(){ return this.peek(); }

my benchmark:

  ko: 22.469ms
json: 1.511ms
noop: 0.115ms 

Subscribing / Unsubscribing using ko.postbox

rniemeyer,

I am currently using postbox to subscribe to events like this for specific reasons:
ko.postbox.subscribe("SomeTopic", function() {
foo()
}, {});

What I would like to know is, can a subscribed topic be unsubscribed? I dont want to call ko.postbox.reset() and lose all of my subscriptions, I just want to unsubscribe one specific topic, something like:

ko.postbox.unsubscribe("SomeTopic");

I didnt see anything in the documentation regarding anything closely similar, but that would be great if that could be added in. Unless, there is a better way to unsubscribe a specific topic?

Thanks,
Steve

getSubscriptionsCount returns wrong result after unsubscribing

getSubscriptionsCount (ko subscribable function) returns wrong results after unsubscribing with ko.postbox.unsubscribeFrom.

For example (also available in http://jsfiddle.net/nv4ptr4d/):
var topic='foo';
console.log(ko.postbox.getSubscriptionsCount('foo')); // 0
ko.postbox.subscribe('foo', function (data) {});
console.log(ko.postbox.getSubscriptionsCount('foo')); // 1
ko.postbox.unsubscribeFrom('foo'); // 0
console.log(ko.postbox.getSubscriptionsCount('foo')); // 1 (should be 0)_

And thanks for this great extension.

Clear subscriptions programatically

Is it possible to clear subscriptions programatically?

I'm using Jasmine to write unit tests and I've noticed events seem to be firing in unexpected ways across tests. It would be good to clear all subscriptions as a clear up between tests as a guard to this.

I've seen another approach mentioned in an issue where they manually unsubscribe on each topic. However comes with risk as an unsubscribe could be missed, not to mention the overhead of managing each subscription.

KO Publish Boolean Does Not Work

You cannot pub/sub with a boolean using .publishOn() and .subscribeTo(), so are forced to use syncWith as a work around.

This is undesirable when the pub/sub only needs to be one way as it adds additional overhead.

ko.postbox.subscribe initializeWithLatestValue

Hello,

I'm using ko.postbox together with ko-amd-helpers. When I reload a module with subscriptions that are initialized I ran into the problem that the handler linked to the subscription is executed in the global context. I expected that the handler was executed in the target-context.

I solved this issue by changing line 53 of knockout-postbox.js from
'action(current.value);' with 'action.call(target, current.value);'

I don't know if this change breaks any other code of your javascript since I'm using only using the basic functionalities of knockout-postbox.js (ko.postbox.subscribe and ko.postbox.publish).

kind regards,

Koen

Unable to use the pub/sub with iframes

hi
i am unable to subscribe view model in the iframe with the publisher view model in the container page. Is there any way to do the same, or is there any way to pass a view model from one page to iframe in same domain.?

Using postbox with AMD knockout components

Dear rniemeyer,

I would like to know how to use postbox with amd knockout components. In your example you manually create the viewmodels and bind directly bind them to the DOM.

However in mine case I register the components using AMD in the following way:

ko.components.register('side-bar', { require: '../../components/settings/side-bar' });

define(['jquery', 'knockout', 'text!./side-bar.html', 'knockout-postbox'], function ($, ko, template) {
function SideViewModel(params){
_this.message = ko.observable().subscribeTo('message', function(val){
console.log(val);
});
}
return { viewModel: SideViewModel, template: template};
});
From another viewmodel I publish a message as follows:
_this.message = ko.observable('test').publishOn('message');

But subscription never fires. Am I doing something wrong?

Regards,

Rabin

topicCache not cleared

I have a knockout component which contains smaller components which use postbox for messaging. When I want to get rid of the component (and all the smaller ones) I call stopPublishingOn and unsubscribeFrom on all objects that are publishing on or are subscribed to a topic. After the cleanup there is no object that would be publishing on or subscribed to any topic used within that component. If I create a new instance of the same component, those smaller components get initialized with values from the previous component instance because the topicCache has not been cleared between disposing the old component and creating a new one. Not sure if it's an issue or just the way postbox works. Is there any way to remove the cached values other than manually removing specific topics and its values from postbox.topicCache?

Does not work for computed

I am working on a complex price estimator. I have multiple sections each with multiple rows that can be dynamically added and removed, each with multiple components. It is completely data-driven, which is neither here nor there, but is a requirement. When any of the component inputs change, the row price, section price, and total price all must be updated. Further complicating the matter, the components are interdependent. Meaning, one component of a row may effect the price of 1 or more components in the row. I originally had this working by sending in the row to each of the individual components in order to find the related components that effected the price of another component. I found your module and thought it would be great for decoupling the components. However, due to the interdependencies, the price and other values require ko.computed values. When I use postbox, the row price does not update when a computed value changes. However, changing a ko.observable value does trigger the computed function to run. The bottom line is that the built in knockout binding works as long as I don't try to bind a postbox subscription to a computed value. When the computed function accesses a computed function bound to a subscribable, the computed function does not trigger. It only triggers when an observable value changes. That is why I think postbox does not work correctly with computed values. It seems to override, rather than augment the built-in KO functionality.

Enhanced context information for .publishOn / .subscribeTo

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]);

Something wrong happens with bower-fethced version

I've fetched the library using bower, and it seems like exports, to which publish and subscribe functions are attached, isn't actually exported to the knockout. At least I couldn't managed to find that in build/knockout-postbox.js.
So observables are extended, but pub/sub functionality isn't exposed, which gives error, when you try to access these functions.
I guess it's because the old bower configuration, which points to old commit.

SetInterval Not Working Within Subscribe Method

The setInterval doesn't get fired(work) when it is within the ko.postbox.subscribe function.

ko.postbox.subscribe('resetsession', function updatesession(e) {

        setInterval(function () { alert("Hello"); }, 3000);

});

Upcoming next version

Is there any plan to bring the next version of knockout-postbox as it's very old?

Confusing behavior with publishOn(), subscribeTo()

I'm trying to setup a scenario where a view model can have an observable property that is "bootstrapped" with initial data from a Postbox topic (likely published from an external view model), but can then be updated independently afterwards without affecting the other subscribers of the same topic.

I was under the impression that observables that only "subscribe" would not publish, and that the opposite were true for observables that only "publish", however I'm not seeing this behavior in practice.

var first = ko.observableArray(['One', 'Two', 'Three'])
var second = ko.observableArray()

first.publishOn('foo')
second.subscribeTo('foo', true)

console.log(first())
// => ["One", "Two", "Three"] as expected

console.log(second())
// => ["One", "Two", "Three"] as expected

second.push('Four')
// why does this affect `first()`?

console.log(first())
// => ["One", "Two", "Three", "Four"] NOT as expected

console.log(second())
// =>  ["One", "Two", "Three", "Four"] as expected

As the code demonstrates, when updating second, the new value also gets assigned to first. This seems wrong, but perhaps I'm just too unfamiliar with the concept of sub/pub systems like this.

Multiple argument for publish()?

Right now publish() only accepts 2 params - event and data. I'm wondering if it is feasible to allow variable data instead? Something like, publish([event], [data1], [data2], [data3]) where subscribers' handler functions can be written as: function ([data1]. [data2]. [data3]).

KO 3.5

Looks like with the change to internal types with KO 3.5 there's now a conflict with KO Postbox requiring the external KO types. I'll do some more investigating but seeing as this project hasn't had an update in 4 years I will likely look for another solution.

Subscribing to events to a specific instance

Dear,

I fail to find a way to subscribe to an event of a specific viewmodel instance.

Let's say I have a ViewModelA of which I have two instances, each publishing the same event.
I would like to subscribe seperatbly to the event of both instances.

Am I correct to state that this is not possible using postbox?
I added a fiddle: http://jsfiddle.net/frederikprijck/zohqLcvo/

As you can see I want to subscribe only to the "MyViewModel_Clicked" event published by myViewModel2, which should not do anything since I am not binding myViewModel2 to my HTML. Still my subscriber get invoked when the event is published from myViewModel1.

ko.postbox.publish() creating duplicate updates

Hi,

First off, this is a great plugin. I've got a question though, that I'm sure is something wrong on my end.

I've got a search box viewModel that publishes updates whenever the search box value changes (using textInput binding).

function searchViewModel() {
  this.searchText = ko.observable("")
     .extend({ rateLimit: { timeout: 200, method: "notifyWhenChangesStop" } })
     .publishOn("searchQuery");
}

ko.applyBindings(new searchViewModel(), document.getElementById('#search'));

This is then subscribed to by a listViewModel that does an AJAX request depending on if it is a query or a blank value.

ko.postbox.subscribe("searchQuery", function(newValue) {
    if(newValue !== '') {
        self.getContacts('?' + self.searchType() + '=' + newValue);
    } else {
        self.getContacts("");
    }
}, self);

This works wonderfully, except when I navigate to the url that is the list of results. /#/contacts (setup using Sammy:

this.get('#/contacts', function(context) {
    loadView('views/list/index.html', new listViewModel());
    ko.postbox.publish("searchQuery", "");

    loadPartialView('views/navigation/index.html', new navigationViewModel(), 'navigationContainer');
});

The first time, this works, but on subsequent navigations to this url (such as going back to it from a detail page), then the value is published twice, resulting in another db call. It's cumulative, too, the third time, two additional calls are made, and it just goes up from there.

Any advice would be much appreciated!

Pub- Sub Issue

Hi,

I am using Publisher and Subscriber with my Knockout models. I am facing problem to update run time generated observable array with Publisher and Subscriber.

Code Example :

In Parent Model
self.Departments = ko.observableArray([]).publishOn("DepartmentList_" + transportId);

In Child Model

this.DepartmentList = ko.observableArray([]).subscribeTo("DepartmentList_" + transportId);

Parent Model contain one child model initially and pub-sub works fine, but if I add another child at run time,after apply bindings, (transportId is same for both childs), second child's DepartmentList does not update when Parent's Departments changes.

Basically pub-sub not working for items added after applyBindings.

It would be great if any body can put some light on it.

Observable Array Tracking

Hi,
I need to track that any thing in observable array has changed, means adding or deleting of a item, modification of any property in any of the child members.
Kindly tell me any suitable way.

For ex :

self.DelayedResponseModelList = ko.observableArray([new DelayedResponseModel()]);

function DelayedResponseModel() {
var self = this;
self.DelayedResponseID = ko.observable(0);
self.UnitID = ko.observable(0);
self.UnitStatusID = ko.observable(0);
self.UnitName = ko.observable('');
self.Status = ko.observable('');
self.IsCurrentlyDR = ko.observable(false);
self.DateStartTime = ko.observable('');
self.TimeStartTime = ko.observable('');
self.DateEndTime = ko.observable('');
self.TimeEndTime = ko.observable('');
self.Reason = ko.observable('');
self.IsMarkedForDelete = ko.observable(false);
self.IsNew = ko.observable(false);
self.IsDirty = ko.observable(false);

}

This observable array is bind with UI, if any property has changed in any of the child from UI , I need a notification.
Is there any good way to achieve this ?

ko.postbox undefined when using AMD

Hi Ryan, I'm using RequireJS in a project and added this library. The documentation makes use of ko.postbox, but with AMD, that's undefined. I realized that with AMD, postbox only uses the 'exports' object. I'm wondering if you would be open to setting ko.postbox = exports so that the option is there to use ko.postbox even when using AMD? Thanks!
-Jake

Alternative options for knockout-postbox

As the knockout-postbox is not under maintenance and long time there is no update, we are looking for an alternative options under knockout. It would be great if you can suggest a few.

Initializing with topic cache when using postbox.subscribe

We're having an issue where our module that publishes on a topic is loaded and publishing before the module that subscribes is loaded. We'd like to be able to pass a boolean to postbox.subscribe indicating that it should initialize to the existing topic cache. Is that possible? Thanks!

add a way to clear one ko.postbox.subscribe() ?

sometimes it's easier not to use an observable but a function directly, but there is no way to clear the subscription. if used in a component, the subscriptions will just duplicate each time the component is initialised.

ko.postbox.subscribe() could return an index that would be fed to ko.postbox.reset()

Unsubscribe

I'm using Jasmine to test my view models. In an init function I'm subscribing with ko.postbox.subscribe("key", function(){});
The behavior that I'm seeing is that for every test that is running, it adds another subscription, so that when I try to test the function inside of subscribe, it's called many times and interferes with the results.

var vm = function(){
 var init = function(){
ko.postbox.subscribe("key", function(){});
};
return{
  Init: init
};
}

it("should do something", function(){
 vm.Init();
 ko.postbox.publish("key", stuff);
// function inside of the subscribe in my vm is called as many times as tests I have that call init
});

//I'd like to do something like this in the beforeEach
var vm;
  beforeEach(function () {
        vm = new Vm();
        ko.postbox.unsubscribeAll(vm);
// or
ko.postbox.unsubscribe(vm, "key");
}

I saw unsubscribeFrom(), but that looks like it only works with an observable.

Thanks for the great library and all your work on answering questions on Knockout.js.

How can I implement async dependencies with knockout-postbox?

I want to implement ajax-powered dependencies between knockout.observables (e.g. country -> province -> city selection) using postbox. When the user selects a country, an ajax request to a dependencyController should be issued, which in turn responds with values for the dependent province and cities fields.

How can I update the observable values in the publishOn/subscribeTo callbacks?

Here is my initial implementation:

 var CountryDependency = function() {
        var self = this;
        this.country = ko.observable("Austria").publishOn("country");
        this.province = ko.observable().subscribeTo("country", function(newValue){
            $.get('/dependencyController?country=' + self.country(), function(response){
               //how can i update province with the value from the server?
                newValue = response.province;
            });
        }).publishOn("province");
        this.cities = ko.observable().subscribeTo("province", function (newValue){
            //another ajax request to dependency controller here
        });
    };

Publish on npm

Since postbox exposes itself as a CommonJS module, it would be great if you could publish it to npm and add a main field to package.json. This would make it easier to use with browserify.

hasSubscriptionsForEvent

Hi,

Is there any way to determine if there is a subscription for a topic?
I used ko.postbox.hasSubscriptionsForEvent for this, but that does not seem to work anymore.

I get error 'Object doesn't support property or method 'hasSubsbscriptionsForEvent' '

Thanks

Support for RequireJS

When using Knockout.js with Require.js, the knockout-postbox.js plugin will not work out of the box unless wrapped with a define(), such as:

define(['knockout'],
function (ko) {
   //...knockout-postbox v0.1.0 goes here...
   return ko;
});

has no method 'subscribeTo'

example.html
error message:
Uncaught TypeError: Object function c(){if(0<arguments.length){if(!c.equalityComparer||!c.equalityComparer(d,arguments[0]))c.I(),d=arguments[0],c.H();return this}a.U.La(c);return d} has no method 'subscribeTo'

browser:chrome v21.0.1180

jsfiddle example with initial value for this.selectedSection.

hello,

about a week ago I came across the knockout-amd-helpers and the knockout-postbox. I love the example in this post (http://jsfiddle.net/rniemeyer/mg3hj/)

I want to use this example to implement all navigations in my webapp. The example provided in jsfiddle is a very good starting point. Only I have one additional requirement:
I want to provide an initial value to the observable that is published.

I tried the following code adaptations in 'http://jsfiddle.net/rniemeyer/mg3hj/'

var MenuModel = function() {
this.name = ko.observable().subscribeTo("nickName");
this.sections = ["Profile", "Notifications"];
this.selectedSection = ko.observable().publishOn("section");
this.selectedSection(this.sections[0]);
};

var MenuModel = function() {
this.name = ko.observable().subscribeTo("nickName");
this.sections = ["Profile", "Notifications"];
this.selectedSection = ko.observable(this.sections[0]).publishOn("section");
};

For some reason the 'Profile' isn't selected automatically. My lack of knowledge will be probably the cause why this isn't working, so I was wondering: has somebody already tried this? if so... how does it to work?

thanks in advance,

Koen

initialisation of syncWith

Hi,

I planned to post an issue for initialization synchronisation on syncWith function but I noticed optionnal parameters (initializeWithLatestValue !) which do what I want.

So, could you just make some short explanation of optionnal parameters (they are not really clear to me) ?

Thank you a lot for you great job.

When publishing a value with a circular reference, a 'cyclic object value' error is thrown

When publishing a value with a circular reference, a 'cyclic object value' error is thrown. This is because of the serialization that happens to fill topicCache.

Code to reproduce:

const foo = {
  id: "foo",
  bar: ko.observable()
}
const bar = {
  id: "bar",
  foo: ko.observable()
}
ko.postbox.subscribe("foo", function() {
  console.log("foo was published");
})

ko.postbox.publish("foo", foo); // console: foo was published

foo.bar(bar);
ko.postbox.publish("foo", foo); // console: foo was published

bar.foo(foo);
ko.postbox.publish("foo", foo); // TypeError: cyclic object value

Is this something that can be solved by the library, or is it something I need to solve in my code?

Subscription singular?

I'm using Knockout 3.2.0 with Postbox.0.4.2. I'm fairly new to KO (month and half) but been a developer for many years and have been doing Angular for a year but looking for a simpler lower learning curve approach for my team. I've decided on KO, Require, RSVP, and Postbox. Since I'm coming at KO new with Components now a part of KO, I'm taking a very Component-centric approach since that makes templates simple html fragments and allows very nice code organization. The problem of course is a clean inter-component messaging that is as loosely coupled as possible. Postbox seemed to be the answer. So that's my environment.

The first place the Postbox is used within my app is following login. The login is a KO component for easy reuse across applications and therefore I don't want any tight coupling. When login is complete, I have the login doing a ko.postbox.publish('logged in', myUserObject); This then allows my application code to be unaware of the login component while able to be informed when login has been completed and what the authentication details are in the provided myUserObject message payload.

Here's where there is confusion on my part. I have 3 components and 1 service that subscribe to the 'logged in' message via ko.postbox.subscribe. Each subscribe has it's own anonymous closure expecting myUserObject as the sole argument. Only 1 subscriber is informed on the publish. The informed subscriber is the first one subscribed. If I comment it out, then the next subscriber get's the message.

Is PostBox suppose to support multiple subscribers? Is there something I'm suppose to be returning from the subscriber function to indicate continued delivery to other subscribers?

I think PostBox is a fantastic idea, leveraging what is already there to add pubsub but it's currently frustrating me that I can't get it to work the way I need it to. I really don't want to go to another pubsub solution because that would not leverage what is already available via KO.

Thanks for PostBox and I look forward to hearing what I may be doing wrong. I can also provide code samples if that would help.

equalityComparer not working properly with boolean values

I wanted to always publish a change to an observable, even when the value itself does not change.

Example:
var alwaysPublish = function() {
return false;
};

self.actionButtonClickNotification = ko.observable(false).publishOn("topic", true, alwaysPublish);

When executing the following repeatedly, the change would publish only once:

self.actionButtonClickNotification(true)

Wheres the following code properly publishes on each execution:

self.actionButtonClickNotification({clicked: true})

Cheers and thanks a lot for the good work
Danny

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.