or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

binding.mdcomponents.mdindex.mdobservables.mdperformance.mdtemplates.mdutils.md
tile.json

templates.mddocs/

0

# Template System

1

2

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.

3

4

## Capabilities

5

6

### Template Rendering

7

8

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

9

10

```javascript { .api }

11

/**

12

* Render template with data

13

* @param template - Template string, node, or function

14

* @param dataOrBindingContext - Data object or binding context (optional)

15

* @param options - Template rendering options (optional)

16

* @param targetNodeOrNodeArray - Target node(s) for rendering (optional)

17

* @param renderMode - How to render into target (optional)

18

* @returns Computed observable for DOM updates or string for string templates

19

*/

20

function renderTemplate(template: string | Node | (() => string | Node)): string;

21

function renderTemplate<T>(

22

template: string | Node | (() => string | Node),

23

dataOrBindingContext: T | BindingContext<T> | null | undefined,

24

options?: TemplateOptions<T> | null | undefined

25

): string;

26

function renderTemplate<T>(

27

template: string | Node | (() => string | Node),

28

dataOrBindingContext: T | BindingContext<T> | null | undefined,

29

options: TemplateOptions<T> | null | undefined,

30

targetNodeOrNodeArray: Node | Node[],

31

renderMode?: "replaceChildren" | "replaceNode" | "ignoreTargetNode"

32

): Computed<void>;

33

```

34

35

**Usage Examples:**

36

37

```javascript

38

import ko from "knockout";

39

40

// Render template as string

41

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

42

43

// Render template with data

44

const data = { name: "World", count: 5 };

45

const html = ko.renderTemplate(

46

"<p>Hello, <span data-bind='text: name'></span>! Count: <span data-bind='text: count'></span></p>",

47

data

48

);

49

50

// Render template into DOM element

51

const targetElement = document.getElementById("content");

52

ko.renderTemplate(

53

"<div data-bind='text: message'></div>",

54

{ message: ko.observable("Dynamic content") },

55

{ afterRender: (elements, data) => console.log("Rendered:", elements) },

56

targetElement,

57

"replaceChildren"

58

);

59

60

// Render template from DOM element

61

const templateElement = document.getElementById("my-template");

62

ko.renderTemplate(templateElement, data, null, targetElement);

63

```

64

65

### Template Options

66

67

Configuration options for template rendering behavior and callbacks.

68

69

```typescript { .api }

70

interface TemplateOptions<T = any> {

71

/** Custom template engine to use */

72

templateEngine?: TemplateEngine;

73

/** Callback after template is rendered */

74

afterRender?: (elements: Node[], dataItem: T) => void;

75

}

76

77

interface TemplateForeachOptions<T = any> extends TemplateOptions<T[]> {

78

/** Alias name for loop variable */

79

as?: string;

80

/** Include items marked as destroyed */

81

includeDestroyed?: boolean;

82

/** Callbacks for array change animations */

83

beforeMove?: (elements: Node[], index: number, dataItem: T) => void;

84

beforeRemove?: (elements: Node[], index: number, dataItem: T) => void;

85

afterAdd?: (elements: Node[], index: number, dataItem: T) => void;

86

afterMove?: (elements: Node[], index: number, dataItem: T) => void;

87

afterRemove?: (elements: Node[], index: number, dataItem: T) => void;

88

}

89

```

90

91

**Usage Examples:**

92

93

```javascript

94

import ko from "knockout";

95

96

// Template with afterRender callback

97

ko.renderTemplate(

98

"<div data-bind='text: message'></div>",

99

{ message: "Hello" },

100

{

101

afterRender: function(elements, data) {

102

// Initialize widgets, apply styling, etc.

103

elements.forEach(el => {

104

if (el.nodeType === 1) { // Element node

105

el.classList.add("rendered");

106

}

107

});

108

}

109

},

110

document.getElementById("target")

111

);

112

113

// Foreach template with animation callbacks

114

const items = ko.observableArray([

115

{ name: "Item 1" },

116

{ name: "Item 2" }

117

]);

118

119

ko.renderTemplate(

120

"<div data-bind='foreach: { data: items, afterAdd: slideIn, beforeRemove: slideOut }'>" +

121

" <div data-bind='text: name'></div>" +

122

"</div>",

123

{

124

items: items,

125

slideIn: function(elements) {

126

elements.forEach(el => {

127

el.style.opacity = "0";

128

el.animate([

129

{ opacity: 0, transform: "translateY(-20px)" },

130

{ opacity: 1, transform: "translateY(0)" }

131

], { duration: 300 });

132

});

133

},

134

slideOut: function(elements) {

135

elements.forEach(el => {

136

el.animate([

137

{ opacity: 1, transform: "translateY(0)" },

138

{ opacity: 0, transform: "translateY(-20px)" }

139

], { duration: 300 });

140

});

141

}

142

}

143

);

144

```

145

146

### Template Engine Management

147

148

Functions for managing and configuring template engines.

149

150

```javascript { .api }

151

/**

152

* Set the global template engine

153

* @param templateEngine - Template engine instance or undefined for default

154

*/

155

function setTemplateEngine(templateEngine: TemplateEngine | undefined): void;

156

```

157

158

**Usage Examples:**

159

160

```javascript

161

import ko from "knockout";

162

163

// Set custom template engine

164

const customEngine = new MyCustomTemplateEngine();

165

ko.setTemplateEngine(customEngine);

166

167

// Reset to default engine

168

ko.setTemplateEngine(undefined);

169

```

170

171

### Template Engine Interface

172

173

Base template engine class for creating custom template processors.

174

175

```typescript { .api }

176

abstract class TemplateEngine {

177

/** Whether template rewriting is allowed */

178

allowTemplateRewriting: boolean;

179

180

/**

181

* Render template source with binding context

182

* @param templateSource - Template source object

183

* @param bindingContext - Current binding context

184

* @param options - Template options

185

* @param templateDocument - Document context (optional)

186

* @returns Array of rendered DOM nodes

187

*/

188

abstract renderTemplateSource(

189

templateSource: TemplateSource,

190

bindingContext: BindingContext<any>,

191

options: TemplateOptions<any>,

192

templateDocument?: Document

193

): Node[];

194

195

/**

196

* Create JavaScript evaluation block

197

* @param script - JavaScript code

198

* @returns Wrapped script block

199

*/

200

createJavaScriptEvaluatorBlock(script: string): string;

201

202

/**

203

* Create template source from template

204

* @param template - Template string or node

205

* @param templateDocument - Document context (optional)

206

* @returns Template source object

207

*/

208

makeTemplateSource(template: string | Node, templateDocument?: Document): TemplateSource;

209

210

/**

211

* Render template with binding context

212

* @param template - Template string or node

213

* @param bindingContext - Binding context

214

* @param options - Template options

215

* @param templateDocument - Document context (optional)

216

* @returns Array of rendered nodes

217

*/

218

renderTemplate(

219

template: string | Node,

220

bindingContext: BindingContext<any>,

221

options: TemplateOptions<any>,

222

templateDocument?: Document

223

): Node[];

224

225

/**

226

* Check if template has been rewritten

227

* @param template - Template to check

228

* @param templateDocument - Document context (optional)

229

* @returns True if template was rewritten

230

*/

231

isTemplateRewritten(template: string | Node, templateDocument?: Document): boolean;

232

233

/**

234

* Rewrite template using callback

235

* @param template - Template to rewrite

236

* @param rewriterCallback - Rewrite function

237

* @param templateDocument - Document context (optional)

238

*/

239

rewriteTemplate(

240

template: string | Node,

241

rewriterCallback: (template: string) => string,

242

templateDocument?: Document

243

): void;

244

}

245

```

246

247

### Built-in Template Engines

248

249

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

250

251

```javascript { .api }

252

/**

253

* Native template engine (default)

254

* Uses browser's native template capabilities

255

*/

256

class NativeTemplateEngine extends TemplateEngine {

257

renderTemplateSource(

258

templateSource: TemplateSource,

259

bindingContext: BindingContext<any>,

260

options: TemplateOptions<any>,

261

templateDocument?: Document

262

): Node[];

263

}

264

265

/**

266

* jQuery templates engine

267

* Integrates with jQuery templates plugin

268

*/

269

class JQueryTmplTemplateEngine extends TemplateEngine {

270

renderTemplateSource(

271

templateSource: TemplateSource,

272

bindingContext: BindingContext<any>,

273

options: TemplateOptions<any>,

274

templateDocument?: Document

275

): Node[];

276

277

createJavaScriptEvaluatorBlock(script: string): string;

278

279

/**

280

* Add named template to jQuery templates

281

* @param templateName - Template name

282

* @param templateMarkup - Template HTML

283

*/

284

addTemplate(templateName: string, templateMarkup: string): void;

285

}

286

```

287

288

**Usage Examples:**

289

290

```javascript

291

import ko from "knockout";

292

293

// Use jQuery templates engine

294

const jqueryEngine = new ko.jqueryTmplTemplateEngine();

295

ko.setTemplateEngine(jqueryEngine);

296

297

// Add named template

298

jqueryEngine.addTemplate("userTemplate",

299

"<div><h3>${name}</h3><p>${email}</p></div>"

300

);

301

302

// Use native engine (default)

303

const nativeEngine = new ko.nativeTemplateEngine();

304

ko.setTemplateEngine(nativeEngine);

305

```

306

307

### Template Sources

308

309

Template source objects that provide template content and metadata.

310

311

```typescript { .api }

312

interface TemplateSource {

313

/** Get or set template text content */

314

text(): string;

315

text(value: string): void;

316

317

/** Get or set template data */

318

data(key: string): any;

319

data<T>(key: string): T;

320

data<T>(key: string, value: T): void;

321

322

/** Get or set template nodes (optional) */

323

nodes?(): Node;

324

nodes?(value: Node): void;

325

}

326

```

327

328

```javascript { .api }

329

const templateSources: {

330

/**

331

* DOM element template source

332

* Uses content of DOM element as template

333

*/

334

domElement: {

335

new(element: Node): TemplateSource;

336

337

text(): string;

338

text(value: string): void;

339

data(key: string): any;

340

data<T>(key: string, value: T): void;

341

nodes(): Node;

342

nodes(value: Node): void;

343

};

344

345

/**

346

* Anonymous template source

347

* For templates created dynamically

348

*/

349

anonymousTemplate: {

350

new(element: Node): TemplateSource;

351

};

352

};

353

```

354

355

**Usage Examples:**

356

357

```javascript

358

import ko from "knockout";

359

360

// Create template source from DOM element

361

const templateElement = document.getElementById("my-template");

362

const domSource = new ko.templateSources.domElement(templateElement);

363

364

// Get template content

365

const templateText = domSource.text();

366

console.log("Template:", templateText);

367

368

// Set template data

369

domSource.data("cacheKey", "unique-identifier");

370

domSource.data("compiled", true);

371

372

// Get template data

373

const cacheKey = domSource.data("cacheKey");

374

const isCompiled = domSource.data("compiled");

375

376

// Create anonymous template

377

const anonymousElement = document.createElement("div");

378

anonymousElement.innerHTML = "<span data-bind='text: message'></span>";

379

const anonymousSource = new ko.templateSources.anonymousTemplate(anonymousElement);

380

```

381

382

### Template Binding Options

383

384

Extended options for template binding in HTML.

385

386

```typescript { .api }

387

interface BindingTemplateOptions extends TemplateOptions {

388

/** Template name or function returning name */

389

name?: string | ((data: any) => string);

390

/** Template nodes to use instead of name */

391

nodes?: Node[];

392

/** Data to pass to template */

393

data?: any;

394

/** Array data for foreach rendering */

395

foreach?: any[];

396

/** Conditional rendering */

397

if?: boolean;

398

ifnot?: boolean;

399

/** Alias for loop variable */

400

as?: string;

401

/** Include destroyed items in foreach */

402

includeDestroyed?: boolean;

403

/** Animation callbacks */

404

beforeMove?: (elements: Node[], index: number, dataItem: any) => void;

405

beforeRemove?: (elements: Node[], index: number, dataItem: any) => void;

406

afterAdd?: (elements: Node[], index: number, dataItem: any) => void;

407

afterMove?: (elements: Node[], index: number, dataItem: any) => void;

408

afterRemove?: (elements: Node[], index: number, dataItem: any) => void;

409

}

410

```

411

412

**Usage in HTML:**

413

414

```html

415

<!-- Named template -->

416

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

417

418

<!-- Template with data -->

419

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

420

421

<!-- Foreach template -->

422

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

423

424

<!-- Conditional template -->

425

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

426

427

<!-- Template with alias -->

428

<div data-bind="template: { name: 'user-template', foreach: users, as: 'user' }">

429

<!-- Inside template: user.name, $index(), $parent, etc. -->

430

</div>

431

432

<!-- Inline template nodes -->

433

<div data-bind="template: { nodes: $element.childNodes, data: currentItem }">

434

<p>This content will be used as template</p>

435

<span data-bind="text: name"></span>

436

</div>

437

438

<!-- Template with animations -->

439

<div data-bind="template: {

440

name: 'animated-item',

441

foreach: items,

442

afterAdd: slideIn,

443

beforeRemove: slideOut

444

}"></div>

445

446

<!-- Named templates in script tags -->

447

<script type="text/html" id="user-template">

448

<div class="user">

449

<h3 data-bind="text: name"></h3>

450

<p data-bind="text: email"></p>

451

<button data-bind="click: $parent.editUser">Edit</button>

452

</div>

453

</script>

454

455

<script type="text/html" id="item-template">

456

<li data-bind="text: title, css: { completed: isDone }"></li>

457

</script>

458

```

459

460

### Custom Template Engine Example

461

462

Example of creating a custom template engine with preprocessing.

463

464

```javascript

465

// Custom template engine with Handlebars-like syntax

466

function HandlebarsTemplateEngine() {

467

this.allowTemplateRewriting = true;

468

}

469

470

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

471

472

HandlebarsTemplateEngine.prototype.renderTemplateSource = function(templateSource, bindingContext, options) {

473

// Get template text

474

let template = templateSource.text();

475

476

// Simple Handlebars-like preprocessing

477

template = template.replace(/\{\{(\w+)\}\}/g, (match, prop) => {

478

return `<span data-bind="text: ${prop}"></span>`;

479

});

480

481

// Create temporary element with processed template

482

const tempDiv = document.createElement("div");

483

tempDiv.innerHTML = template;

484

485

// Apply bindings to processed template

486

ko.applyBindingsToDescendants(bindingContext, tempDiv);

487

488

// Return child nodes

489

return Array.from(tempDiv.childNodes);

490

};

491

492

// Register and use custom engine

493

const customEngine = new HandlebarsTemplateEngine();

494

ko.setTemplateEngine(customEngine);

495

496

// Usage with custom syntax

497

ko.renderTemplate(

498

"<div>Hello, {{name}}! You have {{count}} messages.</div>",

499

{ name: "Alice", count: 5 }

500

);

501

```