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.
To create an observable, assign the ko. observable function to the variable. A default value can be specified in the constructor of the call. Knockout then converts your variable into a function and tracks when the value changes, in order to notify the UI elements associated with the variable.
An observable is useful in various scenarios where we are displaying or editing multiple values and require repeated sections of the UI to appear and disappear as items are inserted and deleted. The main advantage of KO is that it updates our UI automatically when the view model changes.
To activate Knockout, add the following line to a <script> block: ko. applyBindings(myViewModel); You can either put the script block at the bottom of your HTML document, or you can put it at the top and wrap the contents in a DOM-ready handler such as jQuery's $ function.
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) .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With