Unobtrusive Knockout
Asked Answered
S

5

34

I've recently got up to speed with Knockout and I think it's a fantastic framework. However I have one concern.

I'm finding that in non-trivial binding cases, I have snippets of javascript code creeping into my view (markup). In fact quite a few code samples in the Knockout documentation demonstrate this too.

Does this make Knockout inherently obtrusive?

Should I just accept it for what it is and not be worried in practice?

Or are there any patterns/techniques I should be employing to make Knockout unobtrusive?

Smallpox answered 19/11, 2012 at 9:59 Comment(0)
I
21

Great question. I've been writing complex KnockoutJS views for awhile and was never satisfied until I switched to Ryan Niemeyer's class binding provider.

The Knockout ClassBindingProvider allows you to declare your bindings in a JavaScript object and then reference them from a data-class attribute similar to how css classes work. It works great!

See an example TodoMVC app.

Inaugural answered 19/11, 2012 at 21:30 Comment(7)
You also may be interested in some nested functionality that I'm working on. You can see the pull request here: github.com/rniemeyer/knockout-classBindingProvider/pull/15Inaugural
I would go with simplicity here, there is nothing wrong with a little meta data in a html5 data attributeDefaulter
Anders, to what are you referring?Inaugural
To add a 4th layer just to abstract some meta data from the html, data-bind="binding: value" is hardly obtrusive javascript.Defaulter
Sure, it's overkill for small Knockout apps, but there are several other good reasons for it. See hereInaugural
I just didnt like this explicit way of defining bidings so I took it into my own hands to make it better. See my edit in my answer for a Convention over configuration library I've writtenDefaulter
@Defaulter : a bit late to answer but I came here researching the subject. a single and simple onclick is hardly obstrusive javascript too, but still is considered a bad practice... just thinking out loud, the question is still open to me, and since I can't get a clear answer I'll keep it like it is now, obstrusive but I can live with that :-)Scleroprotein
D
16

Try to keep Javascript out of the bindings and only use it for metadata

so instead of doing

<span data-bind="visible: errors().length > 0">You have errors</span>

Use a computed observable

<span data-bind="visible: hasErrors">You have errors</span>

Update: I went ahead and created a Convention over configuration API for KO It can be found here https://github.com/AndersMalmgren/Knockout.BindingConventions/wiki

Instead of doing <button data-bind="click: save">Save</button> you're doing <button data-name="save">Save</button>. The library will understand by convention that you want to hookup the save function to the button click handler. By convention it will also bind enable if a canSave member is present. http://jsfiddle.net/3Ajnj/15/

Defaulter answered 19/11, 2012 at 10:6 Comment(4)
This approach helps clean things up, but it doesn't solve difficult to debug binding errors or the fact that you'll likely end up duplicating your binding code significantly when building larger KO apps.Inaugural
Well the only reason I can see to use your method is to reuse a group of bindings on more than one element. But to specify each and every little binding in a separate JS object sounds extremely cumbersome and actually defeats some of the advantages with MVVM.Defaulter
The example I like to point to is inline styles. They're the fastest way to quickly style small pieces of markup, but they aren't maintainable. Just like external stylesheets, by removing your Knockout bindings from the html, you achieve better maintainability.Inaugural
Missed your last comment there. (Got an upvote so thats why I saw it) My lib above enables you to reuse and group bindings. You just create your own conventionDefaulter
V
5

Should I just accept it for what it is and not be worried in practice?

My understanding is that "unobtrusive" means a few different things.

One aspect of "unobtrusive" is that websites should maintain core functionality on browsers with limited JavaScript support or none at all. To that end, your concern for this principle should depend on your target audience. I've worked on projects where I knew my target audience well enough that I had the luxury of saying, "if you want to take advantage of this web app, use a modern browser like Chrome, with JavaScript enabled." In this case, feel free to go buck wild with the latest, awesomest front-end frameworks out there.

I've worked on other projects where this was not the case we had to be very careful with our usage of frameworks like Knockout. If you're relying heavily on Knockout to do core functionality in your application, then your application is inherently obtrusive. Whether or not this should bother you depends on your target audience.

Another principle of "unobtrusive JS" is a separation of concerns between JavaScript and HTML. I actually debate how strictly important this principle is. I think a more important principle is a separation of concerns between view model logic and display logic, following the MVVM pattern. Knockout does a fantastic job of encouraging clean separation of view/vm concerns, even if you put a bit of JavaScript logic in your data bindings. As long as it's strictly view logic, I think it actually belongs in the view.

Verbosity answered 19/3, 2014 at 18:26 Comment(0)
P
4

I recommend you, that you pay a visit to Ryan's blog and read: "Simplifying and Cleaning Up Views in KnockoutJS", if you haven't done so...

http://www.knockmeout.net/2011/08/simplifying-and-cleaning-up-views-in.html

It explains some nice ways for you to refactor your code, so it doesn't clutter the html and keep it more clean.

Parmer answered 25/8, 2013 at 20:12 Comment(1)
Please also include a summary in your answer (or consider posting this as a comment), to prevent link rot from making this answer obsolete.Chelsae
R
1

An alternative, to the binding provider suggested in the selected answer, is the knockout.unobtrusiveBindingProvider, which is "an unobtrusive, convention-based binding provider for Knockout JS that enables a clean separation of HTML and Knockout databindings".

Redhanded answered 8/8, 2016 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.