When creating an interactive form or other kind of web page, there are a couple of options with knockoutjs. One could create a strongly-typed view and pass a model to it from a controller. On the other hand, one could just as easily start with a plain old html document, and have it initialize itself by calling action methods (JsonResult or otherwise) after the initial load.
Also when starting out the page as an MVC view, you could use HtmlHelpers along with plain old html markup to initialize the view. Another option is to serialize the model state as json to a hidden field, and use that to initialize the view.
In my experience, during first load, there can be a delay when you let ko initialize the view. Whether you construct a viewmodel by passing json from a serialized hidden field, or rely on it to invoke various services to load the data, there is a moment before the page is “ready”. These kinds of delays can be avoided by initializing the page with HtmlHelpers, etc, but such initialization could also incur additional costs (extra initialization logic in the controller, default content in the views, etc).
Which way of initializing a page is the most MVVM? Is it a bad idea to use HtmlHelpers in the views, or to use cshtml at all? If not, where do you draw the line between view and viewmodel?
“The most MVVM” is a hard question to answer, especially considering that we are already mixing patterns with MVC and Knockout.
I would think that letting Knockout do all the work of initilization would be “the most MVVM”, but rigid adherance to a pattern when you are having issues is not a good idea. If KO setting values after the DOM is ready causes problems that you can fix by letting the
HtmlHelpersinitialize the page, then do what works. Since theHtmlHelperswill let you set thedata-bindattributes at the same time, this feels like a good solution, and I have done this before with good results.I would say that storing JSON in a hidden field is not a good idea though. You can directly encode your model into JSON by using this in your javascript:
This is a good solution since the page starts out with the data your controller sends it, without needing a second request.
You may have to think about what trade-offs you want to make. If you want purity and no code duplication, you might have to accept the issue of KO taking a little time to initialize the page. If you want a perfect User Experience, you may have to sacrifice a little purity.