0

It is end of day and my brain is down for the night, but I am working on learning how to use setters when dynamically binding to Html elements. Of the many examples I have read so far, it seems the Urls below are the most helpful on the subject of using setters with knockoutjs bindings but I still do not get the idea or yet understand how it ought to be done.

For instance my viewmodel below (see fiddle) would like to protect the private variables and probably do so by adding some sort of validation code later on.However, right now, it simply needs to get at the parameter or text value entered into the text box by user. What exactly is the best syntax for this kind of operation?

<!-- related bindings: valueUpdate is a parameter for value -->
Your value: <input data-bind="value: someValue, valueUpdate: 'afterkeydown'"/>
Community
  • 1
  • 1
user272671
  • 657
  • 4
  • 13
  • 26

2 Answers2

0

If your trying to achieve two way binding along with the validation, then knockouts computed functions should be the best approach. In your view model have a private variable and and expose ko.computed function for the binding, then in either read/write part of the computed you can do the validation.

Rakesh
  • 157
  • 9
0

Technically you could do that, but it is not the way Knockout is meant to be used. For example, let's say our viewmodel has one <select> and one text <input> binding. Using the private vars to hold the actual values, means we need a writable computed observable to update it, because Knockout only binds properties to your view, not private vars.

function appWithPrivateVars() {
    var selectedItem = ko.observable('Option 3'), //our private vars
        textVal =  ko.observable('Haha');
    this.selected = ko.computed({
        read: function() { return selectedItem(); },
        write: function(value) { /* add validation code here */  selectedItem(value); }
    });
    this.textVal =  ko.computed({
        read: function() { return textVal(); },
        write: function(value) { /* add validation code here */ textVal(value); }
    });
    this.listItems = ['Option 1','Option 2','Option 3'];
    this.get = function() { return selectedItem(); }; //getter
}

Now compare with the code needed for the same viewmodel without caring about private vars (also notice you don't need an explicit getter/setter) :

function appWithProperties() {
    var self = this;
    this.textVal = ko.observable('Haha');
    // example of computed
    this.textValInput = ko.computed({
        read: function() { return self.textVal(); },
        write: function(value) { /* add validation code here */ textVal(value); }
    this.selected = ko.observable('Option 3');
    this.listItems = ['Option 1','Option 2','Option 3'];
}

The thing is you don't need to 'protect' your otherwise accessible model properties because if they are not bound to the view, they will not be able to be modified. Furthermore, you will get yourself in trouble if you use var's at the moment you want to easily serialize your data to JSON with the ko.toJSON function (unless you're willing to rewrite an entire parsing function). Compare the outputs of ko.toJSON for both viewmodels:

Sample data for appWithPrivateVars

// no private vars included, eg. 'selectedItem'
{"selected":"Option 1", // computed prop; not what we need
 "textVal":"Haha",
 "listItems":["Option 1","Option 2","Option 3"]}

See how the 'actual' values are not included in the mapping (which is logical because ko.toJSON doesn't have access to them). Now check out the JSON output for appWithProperties:

{"textVal":"Haha", // actual value
 "textValInput: "Haha", // value filter
 "selected":"Option 1",
 "listItems":["Option 1","Option 2","Option 3"]
} 

Check out the fiddle

webketje
  • 10,376
  • 3
  • 25
  • 54