Reputation: 14593
Take, for example, the situation using knockoutjs:
<div id="container" data-bind="foreach:containers">
<li class="complex-element">...</li>
</div>
Now I want to attach some complex behavior to complex-element
. How do I do that? I can't just attach events directly to complex-element, as they're created and removed dynamically at runtime to match the view model. So, as I see it:
I can riddle my html with data-bind="click:..."
s and data-bind="mouseenter:..."
s but I would rather avoid this if I could. Maybe I'm too rooted in my old MVC ways, but adding open()
, select()
, or dragStart()
functions and isOpen
, isSelected
or isDragging
observable flags to my view model just makes a mess and my intuition tells me that as the app gets bigger that view model is going to become unmanageable. I'd rather keep my data and my presentation separate if possible.
Or I can use jquery delegation to attach events to something that stays fixed. Something like:
$("#container").on('click', '.complex-element button.open', function(e) {
var elem = $(e.target).parents('.complex-element');
...
});
But this wouldn't work as the app gets more complex because what happens if the container is itself wrapped in an element only shown on login (<div id="wrapper" data-bind="if:isLoggedIn">...</div>
). I might as well just bind all events to the body and that's a recipe for disaster.
I found a very cool article on knockmeout.net (http://www.knockmeout.net/2011/07/another-look-at-custom-bindings-for.html) that advocates using custom knockout bindings to drive complex behavior, and this seems to be an awesome solution for widget-like behaviors like autocompletes or date-pickers, but what about just simple old fashioned controllers... would this work?
I guess, after all that, my question is pretty simple: Has anyone used Knockoutjs on a really large web application? And how did you go about it?
Upvotes: 0
Views: 412
Reputation: 15984
If you need to execute some arbitrary js on some rendered elements from the foreach you could use the afterAdd callback
<div id="container" data-bind="foreach: { data: containers,
afterAdd: somefunction }">
<li class="complex-element">...</li>
</div>
I have used KO on a really large web app and the way I went about managing complexity was
Hope this helps.
Upvotes: 2
Reputation: 2685
You could use a different jquery bind:
$(document).on('click', '#container>.complex-element button.open', function(e) {
var elem = $(e.target).parents('.complex-element');
...
});
This would work if #container
does not exist.
There is some work going on in the community to make the knockout bindings unobtrusive and easy to write. For now, knockout offers you dataFor()
which can be seen here: Using unobtrusive event handlers or you can use a little library like this: Introducing the Knockout.Unobtrusive Plugin
Upvotes: 2