KnockoutJS Advanced Search Unknown Schema In ResultSet

Originally published: 03/2011 by J Wynia

In my exploration of KnockoutJS for a variety of projects, I’ve had several instances of a tricky requirement. “Normally”, you know in advance the kind of object your AJAX/JSON search will bring back and you can template the output grid accordingly.

However, in several of my projects, I have very good reasons and situations where the results coming back will be different columns, depending on the search criteria. That means that the KnockoutJS/jQuery template that displays the data can’t go after properties by their names.

That proves tricky to figure out within the layers of frameworks involved. There are plenty of examples of how to do a procedural loop on the list of properties of a Javascript object, but that’s within a normal Javascript “foreach”, not the jQuery templates version.

A normal Javascript foreach includes the name to be used to refer to the object that is the subject of each iteration. For the jQuery template/Knockout version, that variable isn’t visible. Instead, you just see {{each Collection}}.

After a bit of digging, I finally found the information that a couple of “magic” variables are available in the loop: $value and $index. So, if you loop on a collection, the $value is the subject of each iteration. Then, if you take that a step further and loop on the non-array object, its *properties* become the collection and thus $index becomes the name of the property and $value is the value.

Combined, that lets you dig through any unknown object (at least of known depth) and create a display template for it. This works for my need where server-side plugins will determine at runtime what the “shape” of the data being returned is, depending on the inputs.

Here’s a KnockoutJS/jQuery template that displays the values out of an unknown object.

1:  <script type="text/html">
2: {{each resultRow}}
3: <tr>
4: {{each $value}}
5: <td data-bind="text: $value">
6: {{/each}}
7: </tr>
8: {{/each}}
9: </script>

Here’s a version that uses the other “magic” variable: $index, which is the actual property name.


1:  <script type="text/html">
2: {{each resultRow}}
3: <tr>
4: {{each $value}}
5: <td data-bind="text: $index">
6: {{/each}}
7: </tr>
8: {{/each}}
9: </script>


If you use both $index and $value (on multiple levels (which is when things get confusing)), you can build a grid out of any list of properties off an object.


Also hugely helpful is the following combination of investigation tools. You can subscribe to the changes on a portion of your ViewModel and window.alert the new data. If you first call JSON.stringify on that data, you can get a nice, JSON version of the object. Take that JSON over to the JSON Formatter and you can see it all nicely indented and organized.


I find that to be really helpful given you don’t get code completion when writing templates to display this JSON data. The formatted JSON code gives you “documentation” for working off of.


P.S. Sorry for all of the “quoted strings” in this article. It’s a bad habit, but they all seem necessary to me.


P.P.S. This is another of those kind of article where I’m as much posting this for my future self as anything else. if it helps you too, great.

Comments

blog comments powered by Disqus
Or, browse the archives.
© 2003- 2014 J Wynia. Very Few Rights Reserved. This article is licensed under the terms of the Creative Commons Attribution License. Quoted content or content included from others is not subject to that license and defaults to normal copyright.