Search code examples
knockout.jsknockout-postbox

PublishOn not firing when I delete input content


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?


Solution

  • 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("[email protected]").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.