1
votes

I use in my application KockoutJS External Template Engine to be able to load external templates files(so i can use them again in many pages). It's works good and i could use templates in another folder and data displayed correctly

My problem is that i want to call some function after my template is fully rendered and i used this solution with custom bindings (thanks to @RP Niemeyer).

The problem is that custom binding is executed before the template html is fully rendered when using external template file.

But using template which is existed inside my html page the custom binding is executed after the template html is fully rendered.
My template:

<script type="text/html" id="report-template">
    <li>
        <a href="#" data-bind="text: Name, click: $root.ReportsViewModel.ShowParameters"></a>
        <ul data-bind="template: { name: 'report-template', foreach: childItems }">
        </ul>
    </li>
</script>

and that's how i call my custom binding jsTree

<div id="reports-tree">
    <ul data-bind="template: { name: 'report-template', foreach: $root.ReportsViewModel.Reports }, jsTree: $root.ReportsViewModel.Reports"></ul>
</div>

and that's my custom binding code:

ko.bindingHandlers.jsTree = {
    update: function (element, valueAccessor) {
        var reports = ko.utils.unwrapObservable(valueAccessor());
        if (reports.length > 0) {
            $(element).parent().jstree({
                "themes": {
                    "theme": "default",
                        "dots": false,
                        "icons": true,
                        "utl": "/jstree-style.css"
                },
                    "plugins": ["themes", "html_data"]
            });
        }
    }
}
1
Hi! Are you going to react to my answer at any point? - Tomalak
i have animation in my project and i don't want to add timers - ebram khalil
Hm... But I don't add a real timer - setting the timeout to 0 just de-couples the callback function from the current context. Have you tried it? - Tomalak

1 Answers

0
votes

This answer suggests that you can use setTimeout to your advantage: It moves your custom binding to the end of the execution queue.

ko.bindingHandlers.jsTree = {
    update: function (element, valueAccessor) {
        setTimeout(function () {
            var reports = ko.utils.unwrapObservable(valueAccessor());

            if (reports.length > 0) {
                $(element).parent().jstree({
                    "themes": {
                        "theme": "default",
                        "dots": false,
                        "icons": true,
                        "utl": "/jstree-style.css"
                    },
                    "plugins": ["themes", "html_data"]
                });
            }
        }, 0);
    }
};

I'm not sure how well this works with a recursive binding, though.