Force knockout to mark an observable as changed (even if focus is still in the field)
Asked Answered
T

2

5

I develop a project with knockout/breeze.

I would like to know if it is possible to force knockout to mark an observable as changed (even if focus is still in the field). My goad is to notify user that whenever he begin to change the date he has the ability to save it (with a button showed immediately). For example, I have an input field with dates. User begin to edit the date in this field. The observable should only interpret the new encoded date when user leave focus of the field. But I would like to show my Save button as soon as he begin to type something in the input field. I hope I'm clear.

Here is my bindingHandlers for taking care of editing dates in my input:

ko.bindingHandlers.dateRW = {
    //dateRW --> the 'read-write' version used both for displaying & updating dates
    init: function (element, valueAccessor, allBindingsAccessor) {
        var observable = valueAccessor();
        var value = ko.utils.unwrapObservable(valueAccessor);
        //handle the field changing
        ko.utils.registerEventHandler(element, "change", function () {                
            var myDate = moment($(element).val(), "DD/MM/YYYY");
            observable(myDate.toDate());
        });
        //ko.utils.registerEventHandler(element, "keyup", function () {
        //    As soon as user begin to type something, I would like to show my save button
        //});
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        var date = (typeof value !== 'undefined') ? moment(value) : null;
        var dateFormatted = (date != null) ? date.format('DD/MM/YYYY') : '';
        $(element).val(dateFormatted);
    }
};

And my view:

<input type="text" data-bind="dateRW: myDate" />

Unfortunately valueUpdate: 'afterkeydown' does not work because I'm using a custom bindingHandlers.

Hope someone could point me in the right direction.

Thanks.

Tent answered 28/4, 2013 at 9:56 Comment(0)
S
9

Try observable.valueHasMutated()

EDIT In other comments you mentioned that you are binding your save enabled to 'context.hasChanges()' (which is updated from a Breeze EntityManager?).

I believe Breeze doesn't update hasChanges by subscribing to Knockout observable notifications. I think it actually wraps the observable setting function and also checks to make sure that the value is actually changing. In other words I believe you would actually have to change your observables value (and then back) to trigger hasChanges().

Another (not so good) option might be to try and get back to the observable's parent object and get it's EntityAspect. You could then call `setModified()'. Doing all this in a binding handler does seem like a bad idea as it really starts to assume the observable you are binding to is a property on a Breeze entity.

You may be best (no pun intended) to consider an option similar to Michael's answer. Perhaps create a saveEnabled() observable in your viewmodel like:

var saveEnabled = ko.observable(false);
context.hasChanges.subscribe(function() { saveEnabled(true); });

You could then either use the keyup binding that Michael suggests or add another subscribe above on your date observable - and go back to calling valueHasMutated() in the binding handler (if you can find it) .

Studnia answered 28/4, 2013 at 10:7 Comment(2)
I try it but I always got an error: ovservable does not have this method. Any idea why?Tent
I've added more suggestions above.Studnia
O
0

Assuming your save button already has the enable binding tied to an observable, let's call it saveEnabled, you should be able to trigger it using an event handler. Knockout includes an event binding just for this.

<input type="text" data-bind="dateRW: myDate, event: {keyup: function() {saveEnabled(true);}}">

Osteoma answered 28/4, 2013 at 10:40 Comment(1)
My savebutton is directly dependant on breeze context.hasChanges () that's why I'm searching for a cleaner solution like valueHasMutated (for example) which does not work for now for me.Tent

© 2022 - 2024 — McMap. All rights reserved.