Is your feature request related to a problem? Please describe.
I'm currently working on a project with a friend and we have started creating some email template for different use cases. Some of this templates are very flexible to contain things like dynamic lists that are filled by the user input. So we came up with the problem, that MJML has no tags or something like that to loop through a set of arrays items or even render a simple string in a tag. We program our API in python and using jinja2 templating, therefore we need to pass the pre-rendered jinja2 template with jinja2 if else clauses and variables to MJML CLI. This is a step we would like to avoid.
Describe the solution you'd like
It would be nice if MJML supports something that allows passing arguments to the template that will be rendered. e.g.:
the
{{}}Syntax is a syntax from Jinja2, Twig and others use this too and I think its pretty innovative as it differs from HTML
<mjml lang="de">
<!-- OR -->
<mjml lang="lang.short"> <!-- would check if its a available variable-->
<mj-head>
<mj-title><mj-var name="title"/></mj-title>
<!-- OR -->
<mj-preview>{{ title }}</mj-preview>
</mj-head>
<mj-body background-color="#FFFFFF" width="600px">
<mj-section full-width="full-width" background-color="#26292c">
{% if menu | length > 0 %}
<!-- OR -->
<mj-if rule="menu.length > 0">
<mj-column width="70%" vertical-align="middle">
<mj-text align="right">
{% for item in menu %}
<!-- OR -->
<mj-for array="menu.length > 0">
<a href="{{ item.link }}">{{ item.text }}</a>
<!-- OR -->
<mj-link href="item.link"><mj-var name="item.text"/></mj-link>
{% endfor %}
<!-- OR -->
</mj-for>
</mj-text>
</mj-column>
{% endif %}
<!-- or -->
</mj-if>
</mj-section>
</mj-body>
</mjml>
Describe alternatives you've considered
Currently, as I have written above, we use Jinja2 (flask) to prerender the templates and pass it to MJML CLI. Additionally a Python renderer would be awesome too.
Hi @muuvmuuv
It has been discussed multiple time here : #1403 #451 #727 #743
We don't really want to bloat the core engine, as MJML is a Markup Language and not a templating language. We prefer to allow users to plug any templating language to MJML instead of restricting to only one.
Ah yeah I understand, so we will continue using Jinja2, thanks!
+1 on this...a very barebones if-else conditional (like vue.js's v-if and v-else) would be really great.
You can do it with bare javascript, there is no need for a template language.
const shouldClick = Math.random() > 0.5
console.log(`
<mjml>
<mj-body>
<mj-button font-family="Helvetica" background-color="#f45e43" color="white">
${shouldClick ? 'Don\'t click me!' : 'Click me!'}
</mj-button>
</mj-body>
</mjml>
`)
See django-mjml for an example.
Here's a solution that worked for me (after lots of trial and error). I am using the MJML app:
<mj-section full-width="full-width" background-color="#f3f3f3">
<mj-column width="100%">
<mj-text font-size="16px" color="#666666" font-family="Ubuntu" line-height="24px">
<ul>
@foreach ($listOfMissedEpisodes as $missedEpisodeName => $missedEpisodeUrl)
<li>
<a href="{{ $missedEpisodeUrl }}">
{{ $missedEpisodeName }}
</a>
</li>
@endforeach
</ul>
</mj-text>
</mj-column>
</mj-section>
Here is my version using handlebars.js
const path = require('path')
const mjml2html = require('mjml')
const Handlebars = require("handlebars")
module.exports = function ({ file, data }) {
data = data || {}
const mjml = fs.readFileSync(path.resolve(__dirname, file), 'utf8')
const template = Handlebars.compile(mjml)
const { html } = mjml2html(template(data))
return html
}
@codenamezjames ,
If you are using react-mjml you could using native es6 import export without fs read file.
it also integrates nicely with typescript, type safe props, easy components reuse without extra configuration.
Most helpful comment
+1 on this...a very barebones if-else conditional (like vue.js's v-if and v-else) would be really great.