3

So I'm wanting to replace the Knockout templating engine with doT for enhanced performance for my large-scale single-page app. I've been able to get doT.js working with knockout as the templating engine, but i'm having a big issue.

I'm used to using Knockout's event bindings to keep me from having to attach event handlers in my ViewModels. But doT.js doesn't seem to provide this option. I think the primary reason for this is that doT.js just compiles a string of html.

What would be the best way to being able to define events in my views and still use doT.js? Has this been done before?

My thought is that I would have to define my events in a data- attribute and once doT.js is done compiling, throw that html string into a detached DOM element. Then I would have to do something like a .querySelectorAll to find the data- event attributes and attach those to the parent element.

Does anyone have any better thoughts on this?

JSFiddle Example

Here's an example of Knockout.js and doT.js working together (pulled from this example):

http://jsfiddle.net/eeKe7/

JstnPwll
  • 8,585
  • 2
  • 33
  • 56
LordZardeck
  • 7,953
  • 19
  • 62
  • 119

2 Answers2

4

Not sure if I understand correctly, but you're already using doT as the templating engine; why not just let knockout handle the stuff doT doesn't support?

<script id="ko-dot" type="text/html">
    {{~ it.items() :item }}
    <div>
        <span>{{=item.name()}}</span>, 
        <span>{{=item.age()}}</span><br>
        <ul>
            {{~ item.likes() :like }}
            <li data-bind="event: { click: itemClick }">{{= like}}</li>
            {{~}}
        </ul>
    </div>
    {{~}}
</script>

http://jsfiddle.net/sjroesink/ytdLj/

Edit

And if you also want to change the JS notation inside the data-bind, you can use doT also:

<li data-bind="{{=it.event = { click: it.itemClick } }}">{{= like}}</li>

http://jsfiddle.net/sjroesink/ytdLj/2/

I wouldn't recommend this though, as it only limits the flexibility in defining your bindings.

sroes
  • 14,663
  • 1
  • 53
  • 72
  • Oh my gosh you are amazing! I didn't know you could pass back into knockout! Not exactly what I was wanting as I didn't want to use knockout bindings at all, but this helps tremendously. If I don't get an answer that doesn't use knockout bindings, I will definitely accept this! – LordZardeck May 14 '14 at 17:07
  • 1
    something I just noticed is wrong with your code. `itemClick` should be within the array of `likes` but it's not. It's in the root of the viewmodel. How would I change the scope for knockout? – LordZardeck Jun 06 '14 at 15:36
  • You can access the root scope via `$root`: `event: { click: $root.itemClick }` – sroes Jun 06 '14 at 18:25
  • the problem is what if it isn't in the root. See this example: http://jsfiddle.net/ytdLj/3/ – LordZardeck Jun 06 '14 at 21:23
0

You can make it work by giving dot the function code instead of the reference to the function. But I wouldn't recommend it and its ugly!

<button data-bind="click: {{!item.someFunc}}">Click Me...</button>

Example: http://jsfiddle.net/ytdLj/8/

Did anyone manage to solve the context issue?

chrischr
  • 21
  • 2