最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to use jQuery in a Knockout.js Template? - Stack Overflow

programmeradmin1浏览0评论

I'm trying to target an element using jQuery which is embedded in one of my knockout templates:

<script type="text/html" id="video-file-template">
    <div class="video" data-bind="attr: { 'data-index': $index }">
    </div>
</script>

Yet, when I attempt to select $('.video') using jQuery, wrapped in a document ready function, I get an object with a length of 0 returned:

$(document).ready(function() {
    console.log($('.video')); // Returns an object with a length of 0
});

Why is this? Is it because the element is not part of the DOM when my jQuery script is evaluated? If so, how can I target the element when it is loaded into the DOM via Knockout.js?

I'm trying to target an element using jQuery which is embedded in one of my knockout templates:

<script type="text/html" id="video-file-template">
    <div class="video" data-bind="attr: { 'data-index': $index }">
    </div>
</script>

Yet, when I attempt to select $('.video') using jQuery, wrapped in a document ready function, I get an object with a length of 0 returned:

$(document).ready(function() {
    console.log($('.video')); // Returns an object with a length of 0
});

Why is this? Is it because the element is not part of the DOM when my jQuery script is evaluated? If so, how can I target the element when it is loaded into the DOM via Knockout.js?

Share Improve this question asked Mar 10, 2015 at 3:49 marked-downmarked-down 10.4k22 gold badges93 silver badges153 bronze badges 4
  • Where are you using this template(#video-file-template)?? – Madhu Commented Mar 10, 2015 at 4:05
  • Template is not evaluated as DOM element. I think you didn't bind your template using knockout before querying the DOM. – Nhân Nguyễn Commented Mar 10, 2015 at 5:30
  • Yes, defenitely you're trying to execute you jquery statement before KO bindings are applied. Check the order of script execution. – Rango Commented Mar 10, 2015 at 8:58
  • The next question would of course be why you are trying to get the element using jQuery in a $(document).ready callback. I don't know much about your specific scenario, but my guess would be that you'd be a lot better off creating a custom bindingHandler which performs the logic you want. – Robert Westerlund Commented Mar 10, 2015 at 9:34
Add a ment  | 

2 Answers 2

Reset to default 5

It's true that the document is ready before ko.applyBindings finishes, so that's why you're not seeing the element. However, you should not be using jQuery to violate the boundary between your view model and the DOM like that. In knockout, the way to acplish what you need is with custom bindings.

Basically, you define a new knockout binding (like text, value, foreach, etc) and you have access to an init function, which fires when the element is first rendered, and an update function, which fires when the value you pass to the binding is updated. In your case, you would only need to define init:

ko.bindingHandlers.customVideo = {
    init: function (element) {
        console.log(element, $(element));  // notice you can use jquery here
    }
};

And then you use the binding like this:

<div data-bind="customVideo"></div>

Perhaps it's better to add the "video" class and do other initialization right in the init callback:

ko.bindingHandlers.customVideo = {
    init: function (element) {
        $(element).addClass('video');
    }
};

If this feels a little wonky at first, remember there's a very good reason for the indirection. It keeps your view model separate from the DOM it applies to. So you can change the DOM more freely and you can test the view model more independently. If you waited for ko.applyBindings to finish and called some jQuery stuff after that, you'd have a harder time testing that code. Notice that knockout custom bindings are not "special" in any way, and you can see that the built in bindings are defined exactly the same: https://github./knockout/knockout/tree/master/src/binding/defaultBindings

As the previous ments have suggested, it's because your $(document).ready fires before your knockout templates have been rendered.

Whenever I need to do this sort of thing I tend to have an 'init' (or whatever) function on my ko view model that I call after applyBindings has pleted;

So:

var ViewModel = function(){
     var self=this;
     //blah
     self.init = function(){
         //jquery targeting template elements
     }
}
var vm = new ViewModel();
ko.applyBindings(vm);
vm.init();
发布评论

评论列表(0)

  1. 暂无评论