mellis481
mellis481

Reputation: 4168

Valueupdate a computed observable on keyup, but not observable(s) it relies on

I have a computedObservable which is dependent upon the value of another observable that is tied to a text input. Like so, where hasValidAlmUrl is the computedObservable:

<input type="text" data-bind="value: selectedArchive().almUrl" />
<button type="button" data-bind="enable: hasValidAlmUrl">Test</button>

My knockout view model looks like this:

function ArchiveViewModel() {
    var self = this;
    self.selectedArchive = ko.observable(new ArchiveData());
    self.hasValidAlmUrl = ko.computed(function () {
        var almUrl = self.selectedArchive().almUrl();
        if (typeof (almUrl) == 'undefined') return false;
        return almUrl.length > 0;
    }, self);
    ...
};

The hasValidAlmUrl computedObservable works correctly currently, but I want it to update on the keydown event of the <input> instead of when the focus of the <input> changes. I can get this to work by adding a valueUpdate: 'afterkeydown' on the <input>.

What I don't like about that is that these elements are in a modal. Behind the modal overlay is a list of entities for which the entity in the populated modal is part of. When I set the <input> to have a valueUpdate: 'afterkeydown', you can see the grid behind the modal changing as the value of the input changes which I think looks bad.

Is there any way to have a computed observable update on keydown of the observable it's dependent upon BUT not have the dependent observable change on keydown?

Upvotes: 0

Views: 945

Answers (1)

Brandon
Brandon

Reputation: 39222

Create a NEW observable to hold your temporary input, and on some event (focus, apply, etc) copy that value into your original observable:

self.tmpAlmUrl = ko.observable(); // bind your input to this
self.hasValidAlmUrl = ko.computed(function () {
     return (typeof (self.tmpAlmUrl()) !== 'undefined') && self.tmpAlmUrl().length;
});

// call when about to show the modal
self.onDisplayModal = function () {
    self.tmpAlmUrl(self.selectedArchive().almUrl();
});

// call when you want to "apply" the new url
self.onApplyChanges = function () {
    self.selectedArchive.almUrl(self.tmpAlmUrl());
};

Upvotes: 1

Related Questions