Knockout.js textInput binding

Knockout.js added the textInput binding in version 3.2. This has been a big improvement over the standard value binding. Both provide two-way data-binding, but the value binding updates after the input field loses focus, while the textInput binding updates instantly. There has been a valueUpdate parameter available for the value binding, but it has not worked reliably for me. I set the valueUpdate parameter to keypress, but it still did not provide a reliable instant update for me. That has been totally resolved with the new textInput binding. The one thing I am not sure about is the performance impact of using textInput over value, so I have only been using it on fields where it is important to get the instant updates. Some of those fields are quantity or price fields so I can dynamically update the extended price and order totals while the user is entering data and not so much on name fields where it doesn’t matter to get the instant update.

Knockout.js appreciated

We have been preparing to launch a project to production and I had to go back and rework some features. I realize again how much time Knockout.js saves me. I think the biggest help is the two-way data-binding. I remember in the past implementing my own data-binding and that would add hours to a project and would be tough to maintain. Using Knockout.js has eliminated that from my coding and just provides it out of the box. It has literally saved me hours of time.

It has an active Stack Overflow group as well. I was needing to switch an HTML SELECT to a combo box and found several options on Stack Overflow. Having an active group on Stack Overflow is a must for selecting a viable project to use.

Knockout Repeat plug-in

I had a request to display the newest items added at the top of the table, but in the data storage, the newest items needed to be added at the bottom. The built-in foreach binding in knockout does not have an order option. It always traverses the observable array from 0 to the last item. So, I needed to figure out another option for building the table. One option, using only built-in knockout functionality, was to create a second array and using the reverse function on the array to recreate the second array whenever the first array was updated. I just saw too many possible problems with that and, having 2 copies of data, they were liable to get out of sync.

I searched for options on Stackoverflow and found a Repeat plug-in that had been created by Michael Best. It works similar to foreach, but it does have a reverse option which would do what I need. There are some differences in how they work. The main difference is the context that has scope within the loop. In “foreach”, the context changes to the observable array. So, if I specified “foreach: payments”, within the loop, I would just use “amount”. While using the repeat binding, the context stays with the original parent object. So, if I specified “repeat: {foreach:payments, reverse:true}”, within the loop, I would use “$item().amount” to access properties of the object stored in the observable array.

The differences are very minor, but the functionality provided is quite beneficial. This is a plug-in I highly recommend.

Have a Happy Thanksgiving.

Knockout.js Select bindings

Knockout.js is versatile in how you can bind to HTML SELECT inputs. Most of the examples show bindings to simple arrays, but there is a lot more functionality available. The tricky part is knowing where to look. You might think to look for a select binding, but you actually want to look at the documentation for the options binding.

Let me show you an example. Instead of having a simple array of single values to bind to, you want to have an array of objects.

var invlist = [{"id":"PGT_MUM-A","desc":"Decorative pot red mum","combodesc":"A - Decorative pot red mum","price":"25.00","altid":"A"},
{"id":"PGT_MUM-B","desc":"Refill pot red mum","combodesc":"B - Refill pot red mum","price":"20.00","altid":"B"},
{"id":"PGT_MUM-C","desc":"Decorative pot white mum","combodesc":"C - Decorative pot white mum","price":"25.00","altid":"C"},
{"id":"PGT_MUM-D","desc":"Refill pot white mum","combodesc":"D - Refill pot white mum","price":"20.00","altid":"D"}];

In this example, we have inventory items that have an id, description, price and some additional fields. Here is the way the HTML SELECT would look:

<select id="zSaleItem" data-bind="value:currItem, options:invlist, optionsValue:'id', optionsText:'combodesc', optionsCaption:'Item Number'"></select>

In the data-bind, we still specify the value which ties to the field in the viewmodel that this input field is bound to. The rest of the data-binding creates all of the options to be in the select. The first field is “options” which links the array holding all the options to be used to populate the select. In this example, it is “invlist” which is the sample array shown above. The next field is “optionsValue”. This tells the binding what property of the object in the array to place in the value mapped to the viewmodel after a selection is made. “optionsText” specifies the property to be displayed as the text value of the option in the select. When there is not a value selected, you use “optionsCaption” to specify what to display. In this case, it is “Item Number”. Other examples could be “Choose”, “Select”, etc.

I have found this gives a lot of flexibility in defining how you want the SELECT to display and function.

Knockout Auto-complete

I have been using knockout.js extensively in a recent project. I have enjoyed using it. The two-way data-binding has really simplified syncing the display and data, as well as posting data back to the server. I have found the documentation to be superb. Anything that I didn’t find in the documentation, I was able to learn with a quick google and usually found the result I needed on stackoverflow.com.

One feature that wasn’t explained well in the documentation was linking knockout to jQueryUI’s Auto-complete. I found several other blog posts from other people that had implemented it, but I think this post provided the best implementation. There were a couple of items that I tweaked to make it work closer to the way I wanted.

The first change was in the knockout custom binding. On the input text box, I had also defined a change event binding. The event binding was not getting called. There is a function named updateElementValueWithLabel in the definition that is called whenever an item was selected, changed or focused. I added this code to the bottom of the function:

if(typeof allBindings.event.change !== "undefined") {
allBindings.event.change();
}

This code enabled the change event binding to be called. It did create another problem. The above function was also being called when on option was moused over which triggered a focus event in the autocomplete plugin. I didn’t need the change event fired on just receiving focus, so this led to the second change I made.

In the jQueryUI section of the code, I changed the focus option to run just one line of code instead of calling the updateElementValueWithLabel function. That code was:
$(element).val(ui.item.label);
That line placed the option value in the html text box. When someone tabbed out or hit the enter key, the select/change functions would then be called.

I appreciate all the work the original author put in to develop this code. It saved me a tremendous amount of time in figuring out how to implement this and I only needed to make some minor tweaks to get it to work the way I needed it. Thanks Cameron.