API/UI
Templating
Now, this is a tricky one.
Templating is something else. You already have various very strong options on this.
Here we have a very basic but somehow strong templating engine, just enough to render to your needs.
And both API and UI topics lead to this same page. As the templating is same.
First of all the main principle is to separate html with css, js and the backend code.
It's deliberately mixed up nowadays.
That's a preference, as "competitive duck herding" or "volcano climbing" also are.
Those are real hobbies, you can check them. No offence, herders or fireproof people.
We prefer everything plain and simple.
Format
Let's try to keep it simple and not ruin HTML that much, ok?
There are 4 ways you may have to modify your html to enjoy templating:
curly variables : {{data.Name}}
"data-g" attributes : ...div data-g="if|meta.url.view|is:user-details"...
unique identifier closing data attribute to "data-g" attributed TAGs : <div data-g="if|meta.url.view|is:user-details" data-profile>
end comment to "data-g" attributed TAGs : <!--data-profile-->
Below you can see the extend we ruin your HTML for the sake of templating.
It is checked valid HTML, with the W3C, you can check yourself. Just copy and paste there.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{bits.page_title}}</title>
</head>
<body>
<div id="root">
<table data-g="if|meta.url.view|is:user-details" data-profile>
<tr><td>Name:</td><td>{{data.Name}}</td></tr>
<tr><td>Surname:</td><td>{{data.Surname}}</td></tr>
<tr><td>Email:</td><td>{{data.Email}}</td></tr>
<tr><td>Phone:</td><td>{{data.Phone}}</td></tr>
<tr><td>City:</td><td>{{data.City}}</td></tr>
<tr><td>Country:</td><td>{{data.Country}}</td></tr>
</table>
<!--data-profile-->
</div>
</body>
</html>
Templates are generally created once and not modified regularly.
So while trying to ruin them as less as possible,
we had to add an extra unique identifier data-attribute and the same as "comment" for each tag you render.
Otherwise recursive issues are a pain, and performance takes a hit.
Instead don't be lazy and add a unique identifier just before the start tag closes
and the same as comment after the end of the tag which is data-g attributed,
so that it will also help you not get lost at the end, while keeps everything shipshape.
Variables
You need to replace values in a template with the dataset that you have.
Well, otherwise templating does not make sense.
Let's say you have a data like this:
{
"data": {
"Name": "John",
"Surname": "Smith",
"Age": 43,
"Email": "js@somecompany.tld",
"Phone": "+555 444 33 22",
"City": "Tallinn",
"Country": "Estonia"
}
}
You want to show this data in a table on the profile page, you create this template:
<div>
<table>
<tr><td>Name:</td><td>{{data.Name}}</td></tr>
<tr><td>Surname:</td><td>{{data.Surname}}</td></tr>
<tr><td>Age:</td><td>{{data.Age}}</td></tr>
<tr><td>Email:</td><td>{{data.Email}}</td></tr>
<tr><td>Phone:</td><td>{{data.Phone}}</td></tr>
<tr><td>City:</td><td>{{data.City}}</td></tr>
<tr><td>Country:</td><td>{{data.Country}}</td></tr>
</table>
</div>
Good for you, look how nice it renders!
Name: | John |
Surname: | Smith |
Age: | 43 |
Email: | js@somecompany.tld |
Phone: | +555 444 33 22 |
City: | Tallinn |
Country: | Estonia |
Loops and More
This is where it gets kind of interesting...
There are 3 things you can do:
check for a clause with if
loop via each
and use external template file if your template html feels too much to handle...
Oh, and there is also remove and html; the first removes the tag completely, the second sets inner html of the tag.
" if "
The "if" clause in a data-g attribute has a simple pattern.
Every part of is separated by pipe "|".
Clause | Meaning |
if|data.Country|is:Estonia | If "data.Country" value is a string and is Estonia... |
if|data.Country|is:Estonia,Finland | If "data.Country" value is a string and is Estonia or Finland... |
if|data.Country|has:Estonia | If "data.Country" value is an array and has Estonia among values... |
if|data.Age|gt:40 | If "data.Age" value is numeric and greater than 40... |
if|data.Age|lt:40 | If "data.Age" value is numeric and less than 40... |
if|data.Country|not:Estonia | If "data.Country" value is a string and is not Estonia... |
if|data.Country|not:Estonia,Finland | If "data.Country" value is a string and is not Estonia or Finland... |
if|data.Country|dnh:Estonia | If "data.Country" value is an array and does not have Estonia among values... |
if|data.VerifiedUser|set:1 | If "data.VerifiedUser" value is set to any value... |
if|data.VerifiedUser|set:0 | If "data.VerifiedUser" value is not set to any value... |
" each "
The "each" loop in a data-g attribute also is simple.
Parts are separated by pipe "|".
Syntax | Meaning |
each|data.UserList | Within this tag consider every variable as a single item in the UserList array. |
" use "
The "use" keyword usage in data-g attribute has a "include" type of advantage.
Parts are separated by pipe "|". Third part is optional.
Syntax | Meaning |
use|app_users_loop.html | To render this part of the template, include "app_users_loop.html" from the Clone's UI folder. |
use|app_users_loop.html|genes_ui_theme_folder | To render this part of the template, include "app_users_loop.html" from the Genes Core's UI theme folder. |
use|app_users_loop.html|any_other_folder | To render this part of the template, include "app_users_loop.html" from whatever folder you point at the key "any_other_folder" in your config.json. |
Wait. What!? This is all?
Well, no, but, it is better if anything grows with need.
There are very talented and powerful templating languages/extensions, whatever they're called...
Most of the time they are loaded with complex features that have very specific uses for very specific cases.
But to cover these issues the usage gets harder and there may be performance hits.
There may be more to come. As much as the need forces it to grow.
Have patience. And request. Anything you think should be included.