Search code examples
knockout.jsjquery-templates

How can I reach jquery.template contents from within ko.bindingHandler?


There is an element with a knockout.js binding (let it be "A"). The contents of this element is generated using knockout.js/jquery.tmpl templates. Is it possible to get this contents from within of the binding handler called on the element "A"?

Here is a simple example:

<html>
    <head>      
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
        <script src="http://cloud.github.com/downloads/SteveSanderson/knockout/jquery.tmpl.js"></script>
        <script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-1.3.0beta.debug.js"></script>
    </head>
    <body>
        <!-- Some simple tmpls -->
        <script id="wrapperTmpl" type="text/html">
            <div data-bind="showBug:true">                
                <div data-bind="template: 'buggyTmpl'"></div>               
            </div>
        </script>

        <script id="buggyTmpl" type="text/html">
            <div class="buggy">I am out of reach.</div>
        </script>

        <!--
            Knockout won't handle{{tmpl}} calls which are not wrapped in knockout constructions.
        -->
        <div data-bind="template: 'wrapperTmpl'"></div>

        <script>
            <!-- Refers to elements from the child rendered using tmpl -->
            ko.bindingHandlers.showBug = {
                init: function (elem, valueAccessor, allBindingAccessors, model) {
                    var $buggyElem = $(".buggy", elem);
                    console.log("$(elem).html(): ", $(elem).html());        
                    console.log("$('.buggy'): ", $buggyElem);

                }
            };


            ko.applyBindings({});       
        </script>
    </body>
</html>

I would be grateful for any help.


Solution

  • The only issue is that the template gets rendered after your custom binding has executed. You could deal with this by executing your init code in a setTimeout like:

    ko.bindingHandlers.showBug = {
        init: function (elem, valueAccessor, allBindingAccessors, model) {
            setTimeout(function() {
                var $buggyElem = $(".buggy", elem);
                console.log("$(elem).html(): ", $(elem).html());        
                console.log("$('.buggy'): ", $buggyElem);           
            }, 0);
        }
    };
    

    http://jsfiddle.net/rniemeyer/njaeF/