Novice can ignore this section, writable dependency monitoring property is really too advanced, and most of the situation is not used.
In general, the value of the calculated monitor is calculated from the values of other monitoring properties, so it is read-only. It seems strange that we have any way to make him writable. At this point, we just need to provide a callback function to do it.
By using your custom logic to block all read and write operations, you can use the computed monitoring properties as you would with other monitoring properties. Like Obeservables, you can change the values of multiple observable or computered observable properties at once, in the following way:
myViewModel.fullName(‘Joe Smith‘).age(50)
.
Writable computed monitoring properties can be a very useful feature in some scenarios.
Example 1: Decomposing user input
Return to the classic "first name + last name = Full Name" example, you can get things back to the point of view: Let the dependency monitoring property FullName writable, let the user directly enter the full name, The input values are then parsed and mapped to the basic monitoring properties FirstName and LastName:
<Div>First Name:<spanData-bind= "Text:firstname"></span></Div><Div>Last Name:<spanData-bind= "Text:lastname"></span></Div><Divclass= "Heading">Hello,<inputData-bind= "Textinput:fullname"/></Div>
functionMyviewmodel () { This. FirstName = ko.observable (' Planet '); This. LastName = ko.observable (' Earth '); This. FullName =ko.purecomputed ({read:function () { return This. FirstName () + "" + This. LastName (); }, write:function(value) {varLastspacepos = Value.lastindexof (""); if(Lastspacepos > 0) {//Ignore values with no space character This. FirstName (value.substring (0, Lastspacepos));//Update "FirstName" This. LastName (Value.substring (Lastspacepos + 1));//Update "LastName"}}, Owner: This });} Ko.applybindings (NewMyviewmodel ());
This is a case of the Hello World example, the surname and name is not editable, but the name of the first and last names are editable.
The view model above demonstrates the initialization of the computed monitoring property (computed observables) with a simple parameter. For detailed parameter descriptions, see computed observable reference.
Example 2: Select All/Uncheck all items
When presented to the user a range of selectable items, we usually provide full selection and inverse selection. At this point, you can use a bool value to compare the visual representation of whether it is a full selection or a reverse selection. When True indicates that all items have been selected, and when False is returned, the inverse is selected.
Html:
<Divclass= "Heading"> <inputtype= "checkbox"Data-bind= "Checked:selectedallproduce"title= "Select All/none"/>Produce</Div><DivData-bind= "Foreach:produce"> <label> <inputtype= "checkbox"Data-bind= "CheckedValue: $data, checked: $parent. Selectedproduce"/> <spanData-bind= "text: $data"></span> </label></Div>
View Model:
functionMyviewmodel () { This. produce = [' Apple ', ' Banana ', ' celery ', ' Corn ', ' Orange ', ' spinach ' ]; This. selectedproduce = Ko.observablearray ([' Corn ', ' Orange ' ]); This. Selectedallproduce =ko.purecomputed ({read:function () { //comparing length is quick and was accurate if only items from the //The main array is added to the selected array. return This. Selectedproduce (). length = = = This. Produce.length; }, write:function(value) { This. selectedproduce (value? This. Produce.slice (0) : []); }, Owner: This });} Ko.applybindings (NewMyviewmodel ());
Example 3:value Converters
Sometimes you may need to display some data in different formats, from the underlying data to the display format. For example, you store a float type, but the fields that allow users to edit require support for currency units and decimal points. You can do this with a writable computed monitoring property, and then parse the incoming data into the basic float type:
Html:
<Div>Enter Bid Price:<inputData-bind= "Textinput:formattedprice"/></Div><Div>(Raw value:<spanData-bind= "Text:price"></span>)</Div>
View Model:
functionMyviewmodel () { This. Price = Ko.observable (25.99); This. Formattedprice =ko.purecomputed ({read:function () { return' $ ' + This. Price (). toFixed (2); }, write:function(value) {//Strip out unwanted characters, parse as float, then write the //raw data back to the underlying ' price ' observableValue = parsefloat (Value.replace (/[^\.\d]/g, "" ")); This. Price (IsNaN (value)? 0:value);//Write to underlying storage}, Owner: This });} Ko.applybindings (NewMyviewmodel ());
Thus, when a user enters a new price, whatever format the user enters, the text box will format it as a currency symbol and only have two decimal places. This kind of user experience is better. When the user enters data that exceeds two decimal places, the system automatically discards the extra decimals, leaving only two bits, and then the user knows that no more than two decimal places can be entered. Also, you cannot enter a negative number because the system automatically removes the minus sign.
Example 4: Filtering and validating the user's input
Example 1 shows the function of the write filter, if you write a value that does not meet the criteria will not be written, ignoring all the values that do not include spaces.
One more step, you can declare a monitoring property isvalid to indicate whether the last write is legitimate, and then display the corresponding prompt based on the true and false values. There are other simpler ways to do full-law validation (described later), and look at the following example:
Html:
<Div>Enter a numeric value:<inputData-bind= "Textinput:attemptedvalue"/></Div><Divclass= "Error"Data-bind= "Visible:!lastinputwasvalid ()">That ' s not a number!</Div><Div>(Accepted value:<spanData-bind= "Text:acceptednumericvalue"></span>)</Div>
View Model:
functionMyviewmodel () { This. Acceptednumericvalue = ko.observable (123); This. Lastinputwasvalid = Ko.observable (true); This. Attemptedvalue =ko.purecomputed ({read: This. Acceptednumericvalue, write:function(value) {if(IsNaN (value)) This. Lastinputwasvalid (false); Else { This. Lastinputwasvalid (true); This. Acceptednumericvalue (value);//Write to underlying storage}}, Owner: This });} Ko.applybindings (NewMyviewmodel ());
Now, Acceptednumericvalue will only accept numbers, and any other input values will trigger the display of validation information, and the Acceptednumericvalue will be updated.
Note: The above example appears to be too lethal, and the simpler way is to use jquery validation and number class on <input>. Knockout can be used well with jquery validation, for example: Grid editor. Of course, the example above still shows how to filter and validate data using custom logic, and if the validation is complicated and jquery validation is difficult to use, you can use it.
Writable computational monitoring (writable computed observables)