CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-knockout

JavaScript MVVM library that makes it easier to create rich, responsive UIs with automatic UI synchronization through observable data binding

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

templates.mddocs/

Template System

Flexible templating system supporting multiple template engines, template sources, and rendering options for dynamic content generation. The template system provides the foundation for data-driven UI rendering in Knockout.js.

Capabilities

Template Rendering

Core template rendering functions for generating HTML content with data binding.

/**
 * Render template with data
 * @param template - Template string, node, or function
 * @param dataOrBindingContext - Data object or binding context (optional)
 * @param options - Template rendering options (optional)
 * @param targetNodeOrNodeArray - Target node(s) for rendering (optional)
 * @param renderMode - How to render into target (optional)
 * @returns Computed observable for DOM updates or string for string templates
 */
function renderTemplate(template: string | Node | (() => string | Node)): string;
function renderTemplate<T>(
    template: string | Node | (() => string | Node),
    dataOrBindingContext: T | BindingContext<T> | null | undefined,
    options?: TemplateOptions<T> | null | undefined
): string;
function renderTemplate<T>(
    template: string | Node | (() => string | Node),
    dataOrBindingContext: T | BindingContext<T> | null | undefined,
    options: TemplateOptions<T> | null | undefined,
    targetNodeOrNodeArray: Node | Node[],
    renderMode?: "replaceChildren" | "replaceNode" | "ignoreTargetNode"
): Computed<void>;

Usage Examples:

import ko from "knockout";

// Render template as string
const htmlString = ko.renderTemplate("<span>Hello, {{name}}!</span>");

// Render template with data
const data = { name: "World", count: 5 };
const html = ko.renderTemplate(
    "<p>Hello, <span data-bind='text: name'></span>! Count: <span data-bind='text: count'></span></p>",
    data
);

// Render template into DOM element
const targetElement = document.getElementById("content");
ko.renderTemplate(
    "<div data-bind='text: message'></div>",
    { message: ko.observable("Dynamic content") },
    { afterRender: (elements, data) => console.log("Rendered:", elements) },
    targetElement,
    "replaceChildren"
);

// Render template from DOM element
const templateElement = document.getElementById("my-template");
ko.renderTemplate(templateElement, data, null, targetElement);

Template Options

Configuration options for template rendering behavior and callbacks.

interface TemplateOptions<T = any> {
    /** Custom template engine to use */
    templateEngine?: TemplateEngine;
    /** Callback after template is rendered */
    afterRender?: (elements: Node[], dataItem: T) => void;
}

interface TemplateForeachOptions<T = any> extends TemplateOptions<T[]> {
    /** Alias name for loop variable */
    as?: string;
    /** Include items marked as destroyed */
    includeDestroyed?: boolean;
    /** Callbacks for array change animations */
    beforeMove?: (elements: Node[], index: number, dataItem: T) => void;
    beforeRemove?: (elements: Node[], index: number, dataItem: T) => void;
    afterAdd?: (elements: Node[], index: number, dataItem: T) => void;
    afterMove?: (elements: Node[], index: number, dataItem: T) => void;
    afterRemove?: (elements: Node[], index: number, dataItem: T) => void;
}

Usage Examples:

import ko from "knockout";

// Template with afterRender callback
ko.renderTemplate(
    "<div data-bind='text: message'></div>",
    { message: "Hello" },
    {
        afterRender: function(elements, data) {
            // Initialize widgets, apply styling, etc.
            elements.forEach(el => {
                if (el.nodeType === 1) { // Element node
                    el.classList.add("rendered");
                }
            });
        }
    },
    document.getElementById("target")
);

// Foreach template with animation callbacks
const items = ko.observableArray([
    { name: "Item 1" },
    { name: "Item 2" }
]);

ko.renderTemplate(
    "<div data-bind='foreach: { data: items, afterAdd: slideIn, beforeRemove: slideOut }'>" +
    "  <div data-bind='text: name'></div>" +
    "</div>",
    { 
        items: items,
        slideIn: function(elements) {
            elements.forEach(el => {
                el.style.opacity = "0";
                el.animate([
                    { opacity: 0, transform: "translateY(-20px)" },
                    { opacity: 1, transform: "translateY(0)" }
                ], { duration: 300 });
            });
        },
        slideOut: function(elements) {
            elements.forEach(el => {
                el.animate([
                    { opacity: 1, transform: "translateY(0)" },
                    { opacity: 0, transform: "translateY(-20px)" }
                ], { duration: 300 });
            });
        }
    }
);

Template Engine Management

Functions for managing and configuring template engines.

/**
 * Set the global template engine
 * @param templateEngine - Template engine instance or undefined for default
 */
function setTemplateEngine(templateEngine: TemplateEngine | undefined): void;

Usage Examples:

import ko from "knockout";

// Set custom template engine
const customEngine = new MyCustomTemplateEngine();
ko.setTemplateEngine(customEngine);

// Reset to default engine
ko.setTemplateEngine(undefined);

Template Engine Interface

Base template engine class for creating custom template processors.

abstract class TemplateEngine {
    /** Whether template rewriting is allowed */
    allowTemplateRewriting: boolean;
    
    /**
     * Render template source with binding context
     * @param templateSource - Template source object
     * @param bindingContext - Current binding context
     * @param options - Template options
     * @param templateDocument - Document context (optional)
     * @returns Array of rendered DOM nodes
     */
    abstract renderTemplateSource(
        templateSource: TemplateSource,
        bindingContext: BindingContext<any>,
        options: TemplateOptions<any>,
        templateDocument?: Document
    ): Node[];
    
    /**
     * Create JavaScript evaluation block
     * @param script - JavaScript code
     * @returns Wrapped script block
     */
    createJavaScriptEvaluatorBlock(script: string): string;
    
    /**
     * Create template source from template
     * @param template - Template string or node
     * @param templateDocument - Document context (optional)
     * @returns Template source object
     */
    makeTemplateSource(template: string | Node, templateDocument?: Document): TemplateSource;
    
    /**
     * Render template with binding context
     * @param template - Template string or node
     * @param bindingContext - Binding context
     * @param options - Template options
     * @param templateDocument - Document context (optional)
     * @returns Array of rendered nodes
     */
    renderTemplate(
        template: string | Node,
        bindingContext: BindingContext<any>,
        options: TemplateOptions<any>,
        templateDocument?: Document
    ): Node[];
    
    /**
     * Check if template has been rewritten
     * @param template - Template to check
     * @param templateDocument - Document context (optional)
     * @returns True if template was rewritten
     */
    isTemplateRewritten(template: string | Node, templateDocument?: Document): boolean;
    
    /**
     * Rewrite template using callback
     * @param template - Template to rewrite
     * @param rewriterCallback - Rewrite function
     * @param templateDocument - Document context (optional)
     */
    rewriteTemplate(
        template: string | Node,
        rewriterCallback: (template: string) => string,
        templateDocument?: Document
    ): void;
}

Built-in Template Engines

Knockout.js includes several built-in template engine implementations.

/**
 * Native template engine (default)
 * Uses browser's native template capabilities
 */
class NativeTemplateEngine extends TemplateEngine {
    renderTemplateSource(
        templateSource: TemplateSource,
        bindingContext: BindingContext<any>,
        options: TemplateOptions<any>,
        templateDocument?: Document
    ): Node[];
}

/**
 * jQuery templates engine
 * Integrates with jQuery templates plugin
 */
class JQueryTmplTemplateEngine extends TemplateEngine {
    renderTemplateSource(
        templateSource: TemplateSource,
        bindingContext: BindingContext<any>,
        options: TemplateOptions<any>,
        templateDocument?: Document
    ): Node[];
    
    createJavaScriptEvaluatorBlock(script: string): string;
    
    /**
     * Add named template to jQuery templates
     * @param templateName - Template name
     * @param templateMarkup - Template HTML
     */
    addTemplate(templateName: string, templateMarkup: string): void;
}

Usage Examples:

import ko from "knockout";

// Use jQuery templates engine
const jqueryEngine = new ko.jqueryTmplTemplateEngine();
ko.setTemplateEngine(jqueryEngine);

// Add named template
jqueryEngine.addTemplate("userTemplate", 
    "<div><h3>${name}</h3><p>${email}</p></div>"
);

// Use native engine (default)
const nativeEngine = new ko.nativeTemplateEngine();
ko.setTemplateEngine(nativeEngine);

Template Sources

Template source objects that provide template content and metadata.

interface TemplateSource {
    /** Get or set template text content */
    text(): string;
    text(value: string): void;
    
    /** Get or set template data */
    data(key: string): any;
    data<T>(key: string): T;
    data<T>(key: string, value: T): void;
    
    /** Get or set template nodes (optional) */
    nodes?(): Node;
    nodes?(value: Node): void;
}
const templateSources: {
    /**
     * DOM element template source
     * Uses content of DOM element as template
     */
    domElement: {
        new(element: Node): TemplateSource;
        
        text(): string;
        text(value: string): void;
        data(key: string): any;
        data<T>(key: string, value: T): void;
        nodes(): Node;
        nodes(value: Node): void;
    };
    
    /**
     * Anonymous template source
     * For templates created dynamically
     */
    anonymousTemplate: {
        new(element: Node): TemplateSource;
    };
};

Usage Examples:

import ko from "knockout";

// Create template source from DOM element
const templateElement = document.getElementById("my-template");
const domSource = new ko.templateSources.domElement(templateElement);

// Get template content
const templateText = domSource.text();
console.log("Template:", templateText);

// Set template data
domSource.data("cacheKey", "unique-identifier");
domSource.data("compiled", true);

// Get template data
const cacheKey = domSource.data("cacheKey");
const isCompiled = domSource.data("compiled");

// Create anonymous template
const anonymousElement = document.createElement("div");
anonymousElement.innerHTML = "<span data-bind='text: message'></span>";
const anonymousSource = new ko.templateSources.anonymousTemplate(anonymousElement);

Template Binding Options

Extended options for template binding in HTML.

interface BindingTemplateOptions extends TemplateOptions {
    /** Template name or function returning name */
    name?: string | ((data: any) => string);
    /** Template nodes to use instead of name */
    nodes?: Node[];
    /** Data to pass to template */
    data?: any;
    /** Array data for foreach rendering */
    foreach?: any[];
    /** Conditional rendering */
    if?: boolean;
    ifnot?: boolean;
    /** Alias for loop variable */
    as?: string;
    /** Include destroyed items in foreach */
    includeDestroyed?: boolean;
    /** Animation callbacks */
    beforeMove?: (elements: Node[], index: number, dataItem: any) => void;
    beforeRemove?: (elements: Node[], index: number, dataItem: any) => void;
    afterAdd?: (elements: Node[], index: number, dataItem: any) => void;
    afterMove?: (elements: Node[], index: number, dataItem: any) => void;
    afterRemove?: (elements: Node[], index: number, dataItem: any) => void;
}

Usage in HTML:

<!-- Named template -->
<div data-bind="template: 'user-template'"></div>

<!-- Template with data -->
<div data-bind="template: { name: 'user-template', data: selectedUser }"></div>

<!-- Foreach template -->
<div data-bind="template: { name: 'item-template', foreach: items }"></div>

<!-- Conditional template -->
<div data-bind="template: { name: 'details-template', if: showDetails }"></div>

<!-- Template with alias -->
<div data-bind="template: { name: 'user-template', foreach: users, as: 'user' }">
    <!-- Inside template: user.name, $index(), $parent, etc. -->
</div>

<!-- Inline template nodes -->
<div data-bind="template: { nodes: $element.childNodes, data: currentItem }">
    <p>This content will be used as template</p>
    <span data-bind="text: name"></span>
</div>

<!-- Template with animations -->
<div data-bind="template: { 
    name: 'animated-item', 
    foreach: items,
    afterAdd: slideIn,
    beforeRemove: slideOut
}"></div>

<!-- Named templates in script tags -->
<script type="text/html" id="user-template">
    <div class="user">
        <h3 data-bind="text: name"></h3>
        <p data-bind="text: email"></p>
        <button data-bind="click: $parent.editUser">Edit</button>
    </div>
</script>

<script type="text/html" id="item-template">
    <li data-bind="text: title, css: { completed: isDone }"></li>
</script>

Custom Template Engine Example

Example of creating a custom template engine with preprocessing.

// Custom template engine with Handlebars-like syntax
function HandlebarsTemplateEngine() {
    this.allowTemplateRewriting = true;
}

HandlebarsTemplateEngine.prototype = Object.create(ko.templateEngine.prototype);

HandlebarsTemplateEngine.prototype.renderTemplateSource = function(templateSource, bindingContext, options) {
    // Get template text
    let template = templateSource.text();
    
    // Simple Handlebars-like preprocessing
    template = template.replace(/\{\{(\w+)\}\}/g, (match, prop) => {
        return `<span data-bind="text: ${prop}"></span>`;
    });
    
    // Create temporary element with processed template
    const tempDiv = document.createElement("div");
    tempDiv.innerHTML = template;
    
    // Apply bindings to processed template
    ko.applyBindingsToDescendants(bindingContext, tempDiv);
    
    // Return child nodes
    return Array.from(tempDiv.childNodes);
};

// Register and use custom engine
const customEngine = new HandlebarsTemplateEngine();
ko.setTemplateEngine(customEngine);

// Usage with custom syntax
ko.renderTemplate(
    "<div>Hello, {{name}}! You have {{count}} messages.</div>",
    { name: "Alice", count: 5 }
);

docs

binding.md

components.md

index.md

observables.md

performance.md

templates.md

utils.md

tile.json