jQuery document ready with Knockout.js
Asked Answered
B

3

13

I just got thrown into the Umbraco ASP.NET CMS for my latest project, I'm not sure if this is how it across the board but for my setup Knockout.js is doing all the templating.

I'm not too keen on knockout.js but so far it's been pretty straight forward except for when I start adding in some jQuery stuff, the problem I'm having is jQuery is firing before knockout has finished populating the page with all the elements.

The only solution that's worked for me thus far is all my jQuery stuff is wrapped in the setTimeout() function, which obviously is no good.

What's the most efficient way to make jQuery and Knockout work together so jQuery doesn't before knockout is done?

Blindfish answered 18/7, 2014 at 5:55 Comment(2)
Are you calling ko.applyBindings() inside $(document).ready()?Quarles
Now it's more so any jQuery plugins that I run in $(document).ready() fires before knockout finishes. For example with isotope.js, it fires before knockout can finish populating the list, and thus the sorting or filtering functions from isotope don't get passed properly.Blindfish
L
7

I recently had the same issue with the jSignature plugin and my Knockout view. I needed the KO view to have fully rendered before I invoked jSignature, otherwise it didn't size itself correctly.

I fixed it with a template binding and an afterRender callback function to invoke the jQuery work.

Here's the KO docs:

http://knockoutjs.com/documentation/template-binding.html

Here's a quick jsfiddle showing how you can use it:

http://jsfiddle.net/PCbFZ/

The trick is that you can use the afterRender callback of the template binding without actually using a template itself. Instead, you wrap all your existing HTML in a div that will invoke the afterRender callback:

<div data-bind="template: {afterRender: initApp}">
  <!-- your existing HTML here -->
</div>

initApp is the function that does the jQuery work.

I think that should generally do what you need, though if your HTML is particularly complex, or you have many views you need to render inside the one page, you might need to do a bit more work. Let me know how you get on - maybe I can try to help a bit more if this doesn't quite fix your issue as easily as it did mine!


Update - following the comment from JACL below - here's an extended version of the fiddle showing this technique also working with ko-if. Each time you show/hide the 'widget' using the checkbox, a different random colour is applied to indicate the afterRender function doing its work.

http://jsfiddle.net/PCbFZ/15/

Lea answered 21/7, 2014 at 18:24 Comment(3)
My problem was a little different but this answer solved it. Bootstrap popover initialization does not work when "if binding" is used. I used your solution and wrote it to a DOM object after "if binding". Worked great. Thanks.Halfdan
That's a good and interesting use case - because ng-if adds and removes from the DOM, anything jquery-plugin-ish (like a Bootstrap popover) will need reinitialising. I've tweaked the fiddle to show it working with ko if, as well as the initial applyBindings. Maybe you could have a look at it - does that capture how you solved your problem?Lea
Yes it is. Like you said popover needs to be reinitialized. As an example of your answer's updated part, I wrote my popover init function to template init function.Halfdan
A
2

You might use: $(window).load(function(){ /* code */ }); instead of $(document).ready();

Athwart answered 25/8, 2017 at 14:47 Comment(0)
V
0

Perhaps window.load instead of document.ready will do the trick

Vanettavang answered 18/7, 2014 at 6:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.