ultraq / thymeleafjs

A basic implementation of the Thymeleaf templating engine in JavaScript
Apache License 2.0
52 stars 8 forks source link

fragment and insert documentation #26

Open rob-bar opened 5 years ago

rob-bar commented 5 years ago

Hi,

I am trying to make a sub template approach with fragments and inserts. So in the example: template.html is using a fragment from footer.html template.

But I see in the doc the template resolver must be filled in for that. Can you give me some guidance? Much appreciated!

I'm not sure how to do that, this is my npm script.

import Thymeleaf from 'thymeleaf';
import YAML from 'yaml';
import fs from 'fs';
import chalk from 'chalk';

let templateEngine = new Thymeleaf.TemplateEngine(Thymeleaf.STANDARD_CONFIGURATION);
const yamlFileStream = fs.readFileSync(`./src/yml/context.yml`, 'utf8');
const thymeleafFile = `./src/thl/template.html`;
const thymeleafFooterFile = `./src/thl/footer.html`;

// Render template from file
// templateEngine
//   .processFile(thymeleafFooterFile, YAML.parse(yamlFileStream))

templateEngine
  .processFile(thymeleafFile, YAML.parse(yamlFileStream))
  .then(result => {
    fs.writeFile("./dist/index.html", result, (err) => {
      if(err) {return console.log(err);}
      console.log(chalk.blue("./dist/fruits.html") + " was saved!");
     });
  });

this is template.html

<div th:fragment="copy">
  &copy; 2019 The Good Thymes Virtual Grocery
</div>

<h2>This templates engine tests main features of the thymeleaf post to js.</h2>

<h3>th:text</h3>
<p>Hello <span th:text="${username}">(username)</span>

<h3>th:text</h3>
You're using Thymeleaf for <strong th:utext="${language}">Language</strong>!  Wanna see some random fruit?</p>

<h3>th:each</h3>
<ul>
  <li th:each="product: ${fruits}">
    <div th:text="${product}">Oranges</div>
  </li>
</ul>

<h3>th:if</h3>
<div th:if="${shouldLearn}">You should learn thymeleaf</div>

<h3>th:unless (See <a href="https://github.com/ultraq/thymeleafjs/pull/25">pull request</a>)</h3>
<div th:unless="${shouldLearn}">You should not learn thymeleaf</div>

<h3>th:insert</h3>
<!-- tries are here but fail -->
<div th:insert="~{footer :: copy}"></div>
<div th:insert="copy"></div>

<h3>th:replace</h3>
<!-- <div th:replace="${bla}">This is a insert</div> -->

this is footer.html

<div th:fragment="copy">
  &copy; 2019 The Good Thymes Virtual Grocery
</div>
ultraq commented 5 years ago

Sure thing! (I should probably also update the docs with some examples of configuring/using a template resolver now that I re-read it.)

You configure the template resolver as part of the config object you pass in when creating a TemplateEngine instance. If the config object includes a key of templateResolver, then the value is expected to be a function (it can even be an async function):

let templateEngine = new TemplateEngine({
  ...STANDARD_CONFIGURATION,
  templateResolver: (templateName) => {
    // Return the template with the templateName as a string or Promise of a string
  }
});

For the example in your post, ~{footer :: copy} means the template name of "footer", so "footer" will be passed as the templateName parameter to the template resolver function. Your function can then take that and return the necessary template file as a string, eg:

templateResolver: (templateName) => {
  return fs.readFileSync(pathToYourTemplateDirectory + templateName + ".html");
}

Some other examples I can point to that use template resolvers:

I hope that all helps!

rob-bar commented 5 years ago

Alright! works like a charm! thank you for the update. I made a second PR with the tests on the unless processor. 👍

These last two bullet points may come in handy when I create an adaptor for this engine in fractal. https://fractal.build/

rob-bar commented 5 years ago

I've created the fractal adapter here: https://github.com/rob-bar/thymeleafjs-adapter