0

I am using knockout-postbox to mark dirty flag. The code looks like this:

var ProfileModel = function() {
    this.nickName = ko.observable("name1").publishOn("dirty", true);
    this.emailAddress = ko.observable("email1").publishOn("dirty", true);
};

ko.postbox.subscribe("dirty", function(newValue) {
    // enable Save button
}, this);

nickName and emailAddress are tied to input boxes.

<div id="profile">
    <input data-bind="value: nickName" /> </label>
    <input data-bind="value: emailAddress" /></label>
</div>

Steps to recreate the problem:

  1. User goes to nickName input box and delete the content. dirty is raised and Save button is enabled.
  2. User clicks Save button. The change is saved and the Save button becomes disabled.
  3. User goes to emailAddress and delete the content. dirty is NOT raised somehow. User cannot save the change.
  4. User types something on emailAddress or nickName. dirty is raised and Save button is enabled.

You can check out jsfiddle to see it in action. There is no Save button in the jsfiddle example, but just try deleting the content of nickName and then emailAddress. You will see deleting the emailAddress does not raise dirty event.

Is this known bug in knockout-postbox? Is there better way to check dirtyness in knockout?

kennethc
  • 814
  • 1
  • 10
  • 26
  • Yes I see the issue - I suspect it is a bug in postbox. I don't use postbox in that way so can't help. For edit/save/cancel have a look at https://github.com/stevegreatrex/ko.plus - a good edit/cancel/commit capability. – Quango Jan 30 '15 at 16:27

1 Answers1

1

By default, the publishOn functionality of knockout-postbox will not publish the latest value again. In your example, you are publishing an empty string for "dirty" (empty nick name) and then an empty string again (empty email).

publishOn does support passing in your own equality comparer. In your case, you could pass in a function that always returns false.

For example, something like:

var alwaysPublish = function() { return false; }

var ProfileModel = function() {
    this.nickName = ko.observable("Ryan").publishOn("dirty", true, alwaysPublish);
    this.emailAddress = ko.observable("ryan@knockmeout.net").publishOn("dirty", true, alwaysPublish);
    this.log = ko.observableArray();
};

Here is a fiddle: http://jsfiddle.net/rniemeyer/qmbwhk8a/

You can also globally override the compare function by setting ko.postbox.defaultComparer.

RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • This solves my problem. Thank you! One question though: wouldn't it be more intuitive to suppress duplicate values from the same source, rather than suppressing duplicate values to the same target, since `publishOn` is attached to the source? – kennethc Feb 04 '15 at 22:28
  • @kennethc - yes, I might look a little closer at one changes would need to be made. The value is cached at the topic level, so that is what it is getting compared against. I think though that you have a totally valid use case that the lib does not handle intuitively. – RP Niemeyer Feb 04 '15 at 23:16