Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Handlebars vs ES 2015

I thought I'd see how Handlebars and Node 6-compatible ES 2015 compare with a few examples.

Example: Conditional and variable

Handlebars

{{#if @root.flags.premiumIndicator}}
	<div>
		{{{premiumLabel}}}
	</div>
{{/if}}

ES 2015

module.exports = ({ premiumIndicator, premiumLabel }} => {
	if (premiumIndicator) {
		return `
			<div>
				${premiumLabel}
			</div>
		`;
	}
};

Example: partials

Handlebars

{{> ads/top }}
{{!-- adType argument passing through as implicit global --}}

ES 2015

module.exports = ({ adType }) => {
	return require('./ads/top')(adType);
};

Example: nested conditionals

Handlebars

{{#if @root.flags.showIndicators}}
	<div>Indicators</div>
	<ul>
	{{#if @root.flags.premiumIndicator}}
		<li>Premium
	{{/if}}
	</ul>
{{/if}}

ES 2015

const indicators = ({ premiumIndicator }) => {
	if (premiumIndicator) {
		return `<div>${premiumLabel}</div>`
	}
};

module.exports = ({ showIndicators, premiumIndicator }} => {
	if (showIndicators) {
		return `
			<div>Indicators</div>
			<ul>
				${indicators(premiumIndicator)}
			</ul>
		`;
	}
};

Example: Unit testing

Handlebars

const fs = require('fs');
const Handlebars = require('handlebars');
const template = fs.readFileSync('ad.hbs', 'utf8');
const result = Handlebars.compile(template)({ adType: 'top' });
expect(result).to.be('<section>It does what it says on the tin</section>');

ES 2015

const result = require('ad')({ adType: 'top' });
expect(result).to.be('<section>It does what it says on the tin</section>');
@keithamus

This comment has been minimized.

Copy link

commented Oct 11, 2016

@bjfletcher we can have some fun with symbols and tagged templates to create a template language substitute which gets us much closer to the handlebars code:

const truthySymbol = Symbol('truthy');
const falseySymbol = Symbol('falsey');
const endIfSymbol = Symbol('endIf');
const _if = (condition) => condition ? truthySymbol : falseySymbol;
const _endIf = () => endIfSymbol;
const makeTemplate = (strings, ...values) => {
  const template = [];
  const ifNest = [];
  for (let i = 0; i < strings.length; i += 1) {
    if (ifNest.includes(falseySymbol) === false) template.push(strings[i]);
    if (values[i] === truthySymbol || values[i] === falseySymbol) ifNest.push(values[i]);
    if (values[i] === endIfSymbol) ifNest.pop();
  }
  return template.join('');
}

const tmp = ({ flags = {} } = {}) => makeTemplate`
  ${_if( flags.indicators )}
    <div>Indicators</div>
      <ul>
      ${_if( flags.premiumIndicator )}
        <li>Premium
      ${_endIf()}
      </ul>
  ${_endIf()}
`

Now if we run tmp:

tmp() === ``;
tmp( { flags: {} } ) === ``;
tmp( { flags: { indicators: true } } ) === `
  <div>Indicators</div>
    <ul>

    </ul>
`
tmp( { flags: { indicators: true, premiumIndicator: true } } ) === `
  <div>Indicators</div>
    <ul>
      <li>Premium
    </ul>
`
@bjfletcher

This comment has been minimized.

Copy link
Owner Author

commented Oct 11, 2016

Is this any better in terms of readability?

compile`
    ${ helpers.if(flags.indicators) }
        <div>Indicators</div>
        <ul>
        ${ helpers.if(flags.premiumIndicator) }
            <li>Premium
        ${ helpers.endIf() }
        </ul>
    ${ helpers.endIf() }
`;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.