Releases: TogaTech/tApp
Stateful Components
In this release, we built stateful components, a feature to help improve code reusability and make your tApps more dynamic! To see how components work, check out /example/components.html
and config.js
.
Template Compile, While, Else If
We have exposed the tApp.compileTemplate(html, options)
function so that you can compile templates (instead of the compile + render functions).
Additionally, we modified elseif
in templates to be either elseif
or else if
, so there is more flexibility.
Finally, we added while loops to templates. By using {% while condition %}
or {% while (condition) %}
(spaces optional), you can perform a while loop based on a certain condition. Here is an example of using a while loop to render elements of a list:
tApp.renderTemplate("./views/template.html", {
list: ["First element", "Second element", "Third element"],
i: 0
});
In the above code, we initialize a list. Additionally, we define a variable i
to 0. The reason we need to define this here is because variables in the template options are scoped to the entire template's execution (if we just declared it within a code evaluation block {{{ }}}
, the scope would be restricted to only that code evaluation block unless we use window.i
and declare the scope to be global).
<ul>
{{{@ i = 0; }}}
{% while (i < list.length) %}
<li>{{{ list[i] }}}</li>
{{{@ i++; }}}
{% endwhile %}
</ul>
In our template, we have set i = 0
in case i
was changed elsewhere, and we use the silent code execution block {{{@ }}}
to ensure that 0
is not rendered. Then, we declare our while and condition, display our list element with the code execution block, and increment i
in another silent code execution block to ensure that the value of i
is not rendered, and finally, we declare the end of the while
block.
For loops will be coming soon to make iterations easier.
Template Functions
In this release, we added a powerful new feature: template functions. By defining functions in the renderTemplate
options, you can call these functions within your template. Here is an example of displaying a list from an array:
tApp.renderTemplate("./views/template.html", {
list: ["First element", "Second element", "Third element"],
loop: function(elements) {
let returnStr = "";
for(let i = 0; i < elements.length; i++) {
returnStr += `<li>${elements[i]}</li>\n`;
}
return returnStr;
}
});
The loop
function defined in the options loops through all elements inputted and adds an li
tag to the end of the return string with the value of the element, then returns the HTML.
To call this function in the template:
<ul>
{{{ loop(list); }}}
</ul>
It's that simple! You can create any custom functions to embed into your templates for code reusability, for example, custom elements (using functions and parameters in place of HTML tags to render complex and reusable element structures). We will also be adding for and while loops in a later release (in place of this looping function method).
Additionally, we added some more features to templates. To have a comment, surround the comment in {# #}
, and it will not be rendered to the DOM (not even as an HTML comment):
{# Comments #}
Finally, with code execution ({{{ }}}
), we do not render values to the DOM which return null or undefined, but some operations such as setting variables return the current value of the variable, which you might not want rendered to the DOM. Instead of appending null
or undefined
to the end of the expression to return null
and undefined
(which tApp does not render to the DOM), you can use {{{@ }}}
:
{{{@ i = 0; }}}
There were a ton of new templating features in this release, but more are on the way!
Code Execution in Templates
You can now execute code in templates. For example, {{{ 1 + 1 }}}
renders to 2. The code can also be contextual, so if you have a template variable of test: 100
, {{{ test += 1; test + 10 }}}
will render 111 (test
incremented by 1 to 101, test + 10
is rendered), but test
will be 101. The {{ test }}
notation is a pre-render, so the content is safely rendered before any potentially unsafe/destructive code execution, but for an in-line render of the most up-to-date value at the time of top-down render, {{{ test }}}
should be used instead. To escape, use {{\{ test }}}
. NOTE THAT THERE IS CURRENTLY VERY LITTLE SANDBOXING OF THIS EXECUTION, DO NOT EXECUTE UNSAFE CODE. Sandboxing features will be coming in a later release.
Template Else-If and Else Statements
Now, you can add more conditionals to templates by using {% elseif(condition) %}
and/or {% else %}
. Below are some examples:
<p>If statements (using {\% if %}):</p>
<p>If, else if, else if, else</p>
{% if statement == 0 %}
<p>if: 0 (real {{statement}})</p>
{% elseif(statement == 1) %}
<p>elseif: 1 (real {{statement}})</p>
{% elseif (statement == 2) %}
<p>elseif: 2 (real {{statement}})</p>
{% else %}
<p>else: {{ statement }}</p>
{% endif %}
-------------------------------
<p>If, else</p>
{% if statement4 == 0 %}
<p>if: 0 (real {{statement4}})</p>
{% else %}
<p>else: {{ statement4 }}</p>
{% endif %}
-------------------------------
<p>If, else if</p>
{% if statement6 == 8 %}
<p>if: 8 (real {{statement6}})</p>
{% elseif(statement6 == 7) %}
<p>elseif: 7 (real {{statement6}})</p>
{% endif %}
Template If-Statements
In this release, we added template if-statements. There are multiple ways to use an if statement:
{% if variable == "value" %}
<p>Text is shown here only if variable == "value"</p>
{% endif %}
{% if (variable == "value") %}
<p>Text is shown here only if variable == "value"</p>
{% endif %}
{% if(variable == "value") %}
<p>Text is shown here only if variable == "value"</p>
{% endif %}
We will be adding else-if and else in a later release.
Enhance Redirects
tApp.redirect(path, title = document.title)
now takes in a title parameter and replaces the current history state (rather than adding an entry in browser visiting log).
More Caching Fixes
More fixes for disabled caching
Fix No-Cache Bugs
Fixes bugs associated with disabling caching
Fix Bug in Respnse
Previously, in response objects with service worker or tApp.get(path, ignoreCache)
, the URL field was blank. This issue has now been resolved.