Tlx
TLX is a small (< 5K minimized and gzipped) multi-paradigm front-end library supporting: template literals in place of JSX; multi-root templates in HTML, JavaScript, or remote URL references; t-for, t-foreach, t-forvalues with iterable protocol support; t-if attribute directive; custom attribute directives; optional two-way data binding; automatic or manual creation of standards compliant custom elements and components; standards compliant event handlers; a default router; extended lifecycle callbacks; automatic HTML injection protection.
Install / Use
/learn @anywhichway/TlxREADME
TLX v1.0.45
The project has been depreacted in favor of lazui.
TLX is a small (< 5k minimized and gzipped) multi-paradigm front-end library supporting: template literals in place of JSX; multi-root templates using HTML, JavaScript, or remote URL references; t-for, t-foreach, t-forvalues with iterable protocol support; t-if attribute directive; custom attribute directives; optional two-way data binding; automatic or manual creation of standards compliant custom elements and components; standards compliant event handlers; a default router; extended lifecycle callbacks; automatic HTML injection protection.
Tlx can be used in a manner that respects the separation or intergration of development responsibilites between those with a focus on style and layout (HTML and CSS) vs. those with a focus of logic (JavaScript).
Don't forget, give us a star if you like what you see!
- Installation
- Usage
- Examples
- Template Scripting
- Type="text/template" Script Tag
- Attribute Directives
- Working With Components
- Server Side Rendering
- API
undefined tlx.protect()Proxy tlx.reactor(object target={},object watchers={})HTMLElement tlx.el(string,tagName,attributes)HTMLElement tlx.view(HTMLElement el[,object options])function tlx.handlers(object handlers)function tlx.router(object routes)function tlx.component(string tagName,object options)any tlx.escape(any data)tlx.off
- Performance
- Other Reading
- Design Notes
- Acknowledgements
- Release History (reverse chronological order)
- License
Installation
npm install tlx
or use from a CDN
https://unpkg.com/tlx/browser/tlx.js
https://unpkg.com/tlx/browser/tlx.min.js
Usage
NodeJS
const tlx = require("tlx");
Also see section Server Side Rendering.
Browser
Copy the tlx.js file from node_modules/tlx/browser to your desired location and change the path below accordingly.
<script src="tlx.js"></script>
Compatibility
Tlx runs untranspiled in relatively recent Chrome and Firefox. Since Edge does not yet support customElements, it requires a polyfill for components and custom elements to work on that platform.
Tlx is agnostic to the use of build tools and development pipelines. In fact, it is currently only delivered in ES16 format since most people doing substantive development have their own preferred build pipleline that will do any necesssary transpiling.
Examples
See the examples directory for lots of examples, meanwhile here are some basic ones.
Simplest Apps
The simplest apps to write are those that use HTML to define in-line templates and use element name attribute values to support two-way data binding and automatic browser updates through the use of a reactive data model.
<!DOCTYPE html>
<html lang="en">
<body>
<div id="message">
Hello ${firstName}.
</div>
First Name: <input id="name" name="firstName" value="${firstName}">
<script src="tlx.js"></script>
<script>
// create an empty reactive model to share
const model = tlx.reactor();
// bind message area to model
tlx.view(document.getElementById("message"),{model});
// bind field to model and link "name" attribute values to model using linkModel automatically
tlx.view(document.getElementById("name"),{model,linkModel:true})
</script>
</body>
</html>
Note, for large applications, some people find two way data binding and automatic updates can lead to hard to track down infinite loops.
Manual State Updating
Slightly more complex to write are apps that use manual state updating:
<!DOCTYPE html>
<html lang="en">
<body>
<div id="message">
Hello ${firstName}.
</div>
First Name: <input id="name" value="${firstName}" onchange="this.view.linkModel('firstName')(event)">
<script src="tlx.js"></script>
<script>
// create an empty reactive model to share
const model = tlx.reactor();
// bind message area to model
tlx.view(document.getElementById("message"),{model});
// bind field to model
tlx.view(document.getElementById("name"),{model})
</script>
</body>
</html>
Manual State Updating and Re-Rendering
You can take complete control over rendering by not using a reactive model and telling tlx which elements to re-render based on DOM selectors.
<!DOCTYPE html>
<html lang="en">
<body>
<div id="message">
Hello ${firstName}.
</div>
First Name: <input id="name" value="${firstName}" onchange="this.view.linkModel('firstName','#message')(event)">
<script src="tlx.js"></script>
<script>
// create an empty model to share
const model = {};
// bind message area to model
tlx.view(document.getElementById("message"),{model});
// bind field to model
tlx.view(document.getElementById("name"),{model})
</script>
</body>
</html>
From this point onward application development gets more complex, but no more so that development with React, HyperHTML, Vue, or other frameworks. In fact, it is often far simpler.
Template Scripting
Tlx uses JavaScript string template literal notation for templates. Except for atomic attribute templates (see below), all templates should resolve to a valid HTML string.
Atomic attribute templates, i.e. those that involve a single literal, can resolve to any JavaScript type and will be stored directly on the HTMLElement. For example, value="${[1,2,3]}"
Below is a div that conditionally contains repeating content and assumes the provided model:
<div id="names">
${
show
? tlx.el(names.reduce((accum,name) => accum += tlx.el(name,"li"),""),"ul")
: ""
}
</div>
const model = {
show: true,
names: ["joe","bill","mary"]
},
template = document.getElementById("names");
tlx.view(el,{model,template}); // assume el is bound elsewhere
You can also provide templates as strings, but if you want to be able to express them clearly across multiple lines, you will have to escape the interpolation directives, $, and nested backquotes, e.g.
const model = {
show: true,
names: ["joe","bill","mary"]
},
template = `<div>
\${
show
? tlx.el(names.reduce((accum,name) => accum += tlx.el(name,"li"),""),"ul")
: ""
}
</div>`;
tlx.view(el,{model,template});
During processing, four special variables $node, $script, $template, and $view are available. These are the current element or text node and script plus the top level template vdom and view being processed, e.g.
<div id="names" names="${['joe','bill','mary']}">
${
tlx.el($view.names.reduce((accum,name) => accum += tlx.el(name,"li"),""),"ul")
}
</div>
tlx.view(document.getElementById("names"));
Type="text/template" Script Tag
You may occasionally run into issues where you can't create valid HTML with the scripts you wish to embed. This will typically happen if you include what looks like a tag or with complex table generating scripts. Tag issues can usually be resolved with tlx.el(value,tagName). Otherwise, if you take your HTML with embedded scripts and place it within <script id="myscript" type="text/template"> ... </script>, you will be able to pass it to tlx.view as a template. This is because the browser will not attempt to parse it.
Attribute Directives
TLX comes with five built-in attribute directives, t-content, t-if, t-for, t-foreach and t-forvalues.
For all directives, the model currently bound to an element is available as ${model}.
<a name="t-content">t-content</a>
Replaces the innerHTML of the element with the escaped value of t-content. This can be HTML or plain text.
<a name="t-if">t-if</a>
If the value of t-if is truthy, then the element and its nested elements will be displayed,e.g.
<div t-if="true">Will be shown</div>
<div t-if="false">Will not be shown</div>
<a name="t-for">t-for:varname[:in|of]</a>
The value provided to t-for, is the object to process. t-for will provide the key or item bound to varname for any nested string literal templates. The value of t-for can be anything that supports the iterable protocol, e.g.
<div t-for:i:of="${[1,2,3]}">${i}</div>
will render as
<div t-for:i:of="${[1,2,3]}">1,2,3</div>
The qualifiers in and off behave the same way they do for JavaScript loops. If the argument is not provided, then iterables will automatically use of and other objects will use in.
<a name="t-foreach">t-foreach</a>
The value provided to t-foreach, is the array to process. t-foreach will provide the scope variables value, index, and iterable to any nested string literal templates. And, if the iterable is an array, the variable array will also be available, e.g.
<table t-foreach="[1,2,3]">
<tr>
<td>${index}</td><td>${value}</td>
</tr>
</table>
If an array is not provided, the directive is effectively ignored. Con
Related Skills
openhue
338.0kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
338.0kElevenLabs text-to-speech with mac-style say UX.
weather
338.0kGet current weather and forecasts via wttr.in or Open-Meteo
tweakcc
1.4kCustomize Claude Code's system prompts, create custom toolsets, input pattern highlighters, themes/thinking verbs/spinners, customize input box & user message styling, support AGENTS.md, unlock private/unreleased features, and much more. Supports both native/npm installs on all platforms.
