0.16.0 • Published 4 months ago

@optionfactory/ftl v0.16.0

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

FTL - HTML template library

FTL is a templating library targeting browsers similar to thymeleaf

Getting started

  • Import the lib via CDN:
<script src="https://cdn.jsdelivr.net/npm/optionfactory/ftl@{VERSION}/dist/ftl.iife.min.js" integrity="{INTEGRITY}" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  • Init EvaluationContext, optionally registering custom modules
const ec = ftl.EvaluationContext.configure({
        math : {
            isEven: v => v % 2 === 0
        }    
});
  • Define a template using a template tag, a string, a DocumentFragment or a Node
<body>
    ...
    <div id="target"></div>
    <template id="my-template">
        <h1>{{title}}</h1>
    </template>
    ...
</body>
  • Create a template
const template = ftl.Template.fromSelector('#my-template', ec);
  • Render the template
const data = {title: 'Hello World!'};
template.renderToSelector('#target', data);

Attributes evaluation

All attributes starting with data-tpl- (case sensitive) are evaluated in the followind order:

  • data-tpl-if
  • data-tpl-with
  • data-tpl-each
  • data-tpl-value
  • data-tpl-class-append
  • data-tpl-attr-append
  • data-tpl-text
  • data-tpl-html
  • data-tpl-remove
  • data-tpl-*

data-tpl-if

Removes from the DOM the element if the expression evaluates as false

<h3>Tracking:</h3>
<p data-tpl-if="delivered">Your package has been delivered</p>

E.g:

data = {delivered: true}
<h3>Tracking:</h3>
<p>Your package has been delivered</p>

E.g:

data = {delivered: false}
<h3>Tracking:</h3>

data-tpl-with

Sets the context of the fragment to the specified value

data = {
    parent: {
        text: "I'm the parent obj",
        nested: {
            text: "I'm the nested obj",
            label: "fruit",
            fruits: ["apple", "banana", "tomato"]
        }
    }
}
<div data-tpl-with="parent.nested"><p>{{text}}</p></div>

renders to

<div><p>I'm the nested obj</p></div>

It is also possible to assing the evaluated valua to a variable using data-tpl-var. This is useful for referencing it from another context.

<div data-tpl-with="parent.nested" data-tpl-var="nested">
    <p>{{nested.text}}</p>
    <div>
        <h3>fruits</h3>
        <p data-tpl-each="nested.fruits">{{nested.label}}: {{self}}</p>
    </div>
</div>

that will render to

<div>
    <p>I'm the nested obj</p>
    <div>
        <h3>fruits</h3>
        <p>fruit: apple</p><p>fruit: banana</p><p>fruit: tomato</p>
    </div>
</div>

data-tpl-each

Iterates over given array rendering the tag where the attribut is declared, for each array element. Sets the context to the current element.

data = {
    a: [{v: 1}, {v: 2}, {v: 3}]
}
<div data-tpl-each="a">{{ v }}</div>

renders to

<div>1</div>
<div>2</div>
<div>3</div>

data-tpl-text

Evaluates the given expression and places it as text node inside the given element

data = {
    text: "I'm so <i>pretty!</i>"
}
<p data-tpl-text="text"></p>

renders to

<p>I'm so &lt;i&gt;pretty!&lt;/i&gt;</p>

data-tpl-html

Evaluates the given expression and places it as inner html of the given element

data = {
    text: "I'm so <i>pretty!</i>"
}
<p data-tpl-html="text"></p>

renders to

<p>I'm so <i>pretty!</i></p>

data-tpl-remove

Removes the tag, content or whole element where the attribute is specified

data-tpl-remove-tag

<div data-tpl-remove="tag"><p>paragraph</p></div>

renders to

<p>paragraph</p>

data-tpl-remove-body

<div data-tpl-remove="body"><p>paragraph</p></div>

renders to

<div></div>

data-tpl-remove-all

<div data-tpl-remove="all"><p>paragraph</p></div>

renders to

data-tpl-*

It is possible to preceed any attribute with data-tpl-. It will evaluate the expression and set the result as value of an attribute having the name of the given data-tpl- suffix

functions = {
    text: {
        concat: (separator, ...txt) => txt.join(separator)
    }
}
data = {
    color: "green"
}
<p data-tpl-style="#text:concat(' ', 'color:', color)">To be colored</p>

renders to

<p style="color: green">To be colored</p>

Expression evaluation

Object navigation

data = {
    parent: {
        nested: {text: "I'm the nested obj"}
    }
}
<p data-tpl-text="parent.nested.text"></p>

renders to

<p>I'm the nested obj</p>

Nullsafe navigation

data = {
    parent: {
        empty: null
    }
}
<p data-tpl-text="parent.empty?.text"></p>

renders to

<p></p>

Bracket notation navigation

data = {
    today: "tue",
    carToPick: {
        mon: "Ferrari",
        tue: "Lambo",
        wed: "Porsche"
    }
}
<p data-tpl-text="carToPick[today]"></p>

renders to

<p>Lambo</p>

Ternary operator

data = {
    amIRich: false,
    richCar: "Maserati",
    poorCar: "Mazda"
}
<p data-tpl-text="amIRich ? richCar : poorCar"></p>

renders to

<p>Mazda</p>

Call a method

data = {
    parent: {
        nested: {
            fruits: ["apple", "banana", "tomato"]
        }
    }
}
<p data-tpl-text="parent.nested.fruits.join(', ')"></p>

renders to

<p>apple, banana, tomato</p>

Evaluate self

The keyword self refers to the current context

data = {
    parent: {
        nested: {
            fruits: ["apple", "banana", "tomato"]
        }
    }
}
<p data-tpl-each="parent.nested.fruits">{{self}}</p>

renders to

<p>apple</p><p>banana</p><p>tomato</p>

Define and call a function

Call custom defined functions

functions = {
    math: {
        sum: (...addends) => addends.reduce((a,b) => a + b, 0)
    }
}
<p data-tpl-text="#math:sum(1, 5, 3, 65)"></p>

renders to

<p>74</p>

Operators, literals and precedence

  • Dict literals: e.g: {"a": 1, "b": 2}
  • Array literals: e.g: [1,2,3]
  • String literals: e.g: "a" or 'a'
  • Boolean literals: e.g: true or false
  • Number literals: e.g: 3 or 3.1
  • Function calls: e.g: #module:fn() or #fn(1,2,3)
  • Parenthesized expressions: e.g: (a || b) && c
  • Method call: e.g: a.toLowerCase()
  • Array access: e.g: a[b] or a?.[b]
  • Member access: e.g: a.b or a?.b
  • Logical not: e.g: !a
  • Relational operators: e.g: a >= b or a > b or a <= b or a <= b
  • Equality operators: e.g: a == b or a != b
  • Logical and expressions: e.g: a && b
  • Logical or expressions:e.g: a || b
  • Ternary operator: e.g: a ? b : c
0.16.0

4 months ago

0.15.0

5 months ago

0.14.0

5 months ago

0.12.0

5 months ago

0.13.0

5 months ago

0.11.0

5 months ago

0.10.0

6 months ago

0.9.0

6 months ago

0.8.0

1 year ago