Symbiote.js
Get startedTemplatesPropertiesAttributesFlagsContextLifecycleList itemsStylingSSRRoutingPubSubEcosystemLive examples

Templates

The core template mechanic in Symbiote.js - is a native browser HTML-string parsing via standard DOM API methods. That's the fastest way to create component template instance in object model representation.

html

We have a html helper tag function, that manage to construct templates using compact binding-maps:

import { html } from '@symbiotejs/symbiote';

const myTemplate = html`
  <button ${{onclick: 'onBtnClick'}}>Click me!</button>
`;

In this example, we've created the button and connected it to a onBtnClick handler function, which should be defined in a component state.

As you can see, every binding-map - is a simple JavaScript object, that describes connections between the own inner element properties and the component's data. It is a standard JavaScript template literal syntax with no any special additions.

Note, that in Symbiote.js you can define and describe template outside the component's context (this) visibility, this is a clear abstraction. That helps to make manipulations with templates much more flexible than in some other libraries.

Binding to a text node

Let's see onto the more detailed example:

import Symbiote, { html } from '@symbiotejs/symbiote';

class MyComponent extends Symbiote {

  init$ = {
    name: 'John',
    btnTxt: 'Click me!',
    onBtnClick: () => {
      console.log('Button clicked!');
    },
  }

}

MyComponent.template = html`
  <h1>Hello {{name}}!</h2>
  <button ${{onclick: 'onBtnClick'}}>{{btnTxt}}</button>
`;

In this example we have a new type of template bindings to a text nodes, which are defined with a double braces syntax - {{myProp}}.

Binding to nested properties

Symbiote.js allows to bind properties to the nested properties of the elements:

MyComponent.template = html`
  <div ${{'style.color': 'myCssValue'}}>Some text...</div>
`;

Also, you can bind your props to the nested component's state directly, using $-proxy:

MyComponent.template = html`
  <my-component ${{'$.nestedPropName': 'propName'}}></my-component>
`;

Binding to HTML-attributes

To bind some property to the element's attribute, use @ prefix:

MyComponent.template = html`
  <div ${{'@hidden': 'isHidden'}}></div>
`;

Type casting

You can transform any type of property value to boolean type (true or false), using ! symbol.

Inversion example:

html`<div ${{'@hidden': '!innerText'}}> ... </div>`;

Double inversion example:

html`<div ${{'@contenteditable': '!!innerText'}}> ... </div>`;

Property Tokens (Property key prefixes)

Named context property /

To bind something to some named data context property, use the named prefix:

html`<div ${{textContent: 'MY_APP/propName'}}> ... </div>`;

Shared context property *

To share a property with other components in a same usage context, use the shared context token:

html`<div ${{textContent: '*propName'}}> ... </div>`;

Inherited context property ^

To get the direct access to some property of the top level component (cascade data model), use the inheritance token:

html`<div ${{textContent: '^propName'}}> ... </div>`;

CSS Data property --

To initiate some property from the CSS Data, you can do as follows:

html`<div ${{textContent: '--prop-name'}}> ... </div>`;

More details about Symbiote-component's context you can find in Context section.

Slots

Slots allow you to define placeholders in your template that can be filled with any external markup fragment.

Default template slot:

<div class="my-wrapper">
  <slot></slot>
</div>

Named template slots:

<header>
  <slot name="header"></slot>
</header>
<article>
  <slot name="article"></slot>
</article>
<footer>
  <slot name="footer"></slot>
</footer>

Element references

If you need an element reference somewhere in your code logics, use ref attribute for your template element:

html`
  <div>
    <div ${{ref: 'div1'}}></div>
    <div ${{ref: 'div2'}}></div>
  </div>
`;

or, to get the same effect:

html`
  <div>
    <div ref="div1"></div>
    <div ref="div2"></div>
  </div>
`;

Reference name should be unique for each element (like an element's id). Then you can use ref collection to get those elements in your code without any additional DOM search:

class MyComponent extends Symbiote {
  renderCallback() {
    this.ref.div1.contenteditable = true;
    this.ref.div2.style.color = 'red';
  }
}

Dynamic list rendering

To render efficient dynamic reactive list of elements, use the itemize API:

class MyComponent extends Symbiote {
  init$ = {
    listData: [
      {
        firstName: 'John',
        secondName: 'Snow',
      },
      {
        firstName: 'Jane',
        secondName: 'Stone',
      },
    ],
  }
}

MyComponent.template = html`
  <h1>My list:</h1>
  <ul ${{itemize: 'listData'}}>
    <li>{{firstName}} {{secondName}}<li>
  </ul>
`;

More information about itemize API you can find at the List items section.

External customizable templates

Symbiote.js allows you to create components, that can connect templates defined in common HTML-document.

To use this feature, set the allowCustomTemplate flag:

class MyComponent extends Symbiote {

  allowCustomTemplate = true;

}

Then, define necessary templates in the HTML markup:

<template id="first">
  <h1>{{headingText}}</h1>
</template>

<template id="second">
  <h2>{{headingText}}!</h2>
</template>

Ok, now we can use them:

<my-component use-template="#first"><my-component>

<my-component use-template="#second"><my-component>

Proceed to Properties

11.12.2025
JSDA is very simple
Why JSDA is the best way to build web apps
28.09.2024
It was really possible?
Symbiote.js as an answer to many questions
17.09.2024
Smart HTML-tags
Simple recipe with the Artificial Intelligence
25.01.2024
Symbiote VS Lit
David and Goliath: differences, pros and cons...
18.01.2024
Symbiote.js 2.x
The new major version is released. Let's see what's new...
RND-PRO.com © 2025