Search code examples
knockout.jsknockout-3.0knockout-kendo

Prevent knockout from applying bindings to elements that are not visible


I am rendering a large recursive data structure, and am trying to allow users to be able to toggle editing of individual elements within that structure. I am having trouble with performance when applying the bindings due to the editor binding being applied to all elements, even if they are not visible yet.

<div data-bind="visible: isEditable()">
    <textarea data-bind="kendoEditor: { value: name }" > </textarea>
    <button type="button" data-bind="click: toggleEdit(false)">Update</button>
</div>

If you look at the following example, it appears to work correctly. You can click on an element, it will enable an editor, you can click update and the changes will be applied.

jsfiddle 1

However, if you look at the following example where I have added more data, the initial load is very slow due to applying the kendoEditing binding to all elements in the list.

jsfiddle 2

Is there any way to prevent bindings from being applied to elements that are not yet visible?


Solution

  • You're doing an awful lot of toggling in advance, because your click bindings should be getting a function, not a snippet of code. This is a common mistake.

    To avoid binding a million editors, you can just swap templates in and out rather than having visible and invisible elements:

    <ul data-bind="template: { name: 'itemTmpl', foreach: Items }"></ul>
    <script id="itemTmpl" type="text/html">
    <li>
        <div data-bind="template: isEditable() ? 'editable' : 'notEditable'"></div>
        <ul data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
    </li>
    </script>
    <script id="notEditable" type="text/html">
        <span data-bind="html: name, click: toggleEdit.bind(null,true)">
        </span>
    </script>
    <script id="editable" type="text/html">
        <textarea data-bind="kendoEditor: { value: name }"></textarea>
        <button type="button" data-bind="click: toggleEdit.bind(null, false)">Update</button>
    </script>
    

    Updated Fiddle