KnockoutJS foreach binding and an old-school ASP.NET Repeater

Stuck with ye olde ASP.NET Webforms? It doesn't mean you have to miss out on all the good javascript fun (which is, in fact, also an old technology). At my current client (being a consultant and all), we have carefully introduced Knockout.js for the more complex screens. To be honest, it's only used in two screens at the moment, but the team is open to it being used more and more. That being said, we don't regard it as the silver bullet, and will choose our technology based on speed of development and maintainability.

Anyway, Knockout.js is great and has made certain portions of javascript much easier and cleaner. What remained a challenge, was how to integrate it with the way we did grids (tables of data). We used a Repeater to render a regular HTML table. Also, some custom scripts were used to add certain common behavior to all our tables.

This made it hard if not impossible for us to use the foreach binding. In essence, we wanted to keep the code for building and populating the table on the server side, but then have the rows bound to our Knockout.js viewmodels.

It turns out this is very easy. Instead of using the aforementioned foreach binding, you can use the with binding. Just put the following in your markup (in the ItemTemplate of your Repeater):

<tr data-bind="with: myItems()[<%# Container.ItemIndex %>]"></tr>
Then, inside your row, you can bind your cells or other controls to the properties of your viewmodel.

If you want to go the extra mile, you could have custom bindings that don't set the value/text/whatever of the controls initially, so the initial rendering is handled 100% server-side. With the normal bindings, Knockout.js will set the values when you call applyBindings(), even though the server already set these values. But in our case, it didn't slow things down. The important thing was that the bindings worked, so we could use it to hide/show/calculate certain values in certain cells.

So you see, the old lady (WebForms) just won't sink! Which is testament to the great work the ASP.NET devs did from the get-go.

Edit: You can find a working example on my GitHub.