Skip to content

Instantly share code, notes, and snippets.

@sparhami
Last active March 24, 2024 20:42
Show Gist options
  • Star 40 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sparhami/197f3b947712998639eb to your computer and use it in GitHub Desktop.
Save sparhami/197f3b947712998639eb to your computer and use it in GitHub Desktop.
Example of Closure Templates compiling to Incremental DOM instructions

How a template for some sort of post may be translated to javascript. The following examples use the syntax from Closure templates, but any templating language can be used.

Starting with the content of a post, we might have a template like the following:

{namespace some.namespace}


/**
 * @param postInfo The data for the post
 */
{template .postContent}
  <div>{$postInfo.title}</div>
  
  <div>
    <img src="{$postInfo.author.image}">
    <span>{$postInfo.text}</span>
  </div>
{/template}

Which might translate to:

function some.namespace.postContent(data) {
  var postInfo = data.postInfo.
  elementOpen('div', null);
    text(postInfo.title);
  elementClose('div');
  elementOpen('div', null);
    elementVoid('img', null, null,
      'src', postInfo.author.image);
    elementOpen('span', null);
      text(postInfo.text);
    elementClose('span');
  elementClose('div');
}

Now to create a card template that we can put our post inside:

/**
 * @param classes Extra classes for the card
 * @param content The card's content
 */
{template .card}
  <div class="card{if $classes} ${classes}{/if}">
    {$content}
  </div>
{/template}

Which might translate to:

function some.namespace.card(data) {
  var classes = data.classes;
  var content = data.content;
  elementOpen('div', null, null,
      'class', 'card' + classes ? ' ' + classes : '');
    content();
  elementClose('div');
}

Before passing our content to the card, lets add a check to see if the post is loading, and if so, render a spinner instead:

/**
 * @param postInfo The data for the post
 */
{template .post}
  {call some.namespace.card}
    {param classes kind="text"}supercard{/param}
    {param content kind="html"}
      {if $postInfo.isLoading}
        {call some.namespace.spinner /}
      {else}
        {call .postContent data="all" /}
      {/if}
    {/param}
  {/call}
{/template}

Which might translate to:

function some.namespace.post(data) {
  some.namespace.card({
    classes: 'supercard',
    content: function() {
      if (data.isLoading) {
        some.namespace.spinner();
      } else {
        postContent(data);
      }
    }
  })
}

Finally, lets render an array of posts:

/**
 * @param postInfoArray An array of postInfo
 */
{template .postList}
  <div>
    {foreach $postInfo in $postInfoArray}
      {call .post}
        {param postInfo: $postInfo /}
      {/call}
    {/foreach}
  </div>
{/template}

Which might translate to:

function some.namespace.postList(data) {
  var postInfoArray = data.postInfoArray;
  elementOpen('div', null);
    for (var i = 0; i < postInfoArray.length; i++) {
      var postInfo = postInfoArray[i];
      some.namespace.post({
        postInfo: postInfo      
      });
    }
  elementClose('div');
}
@MadebyAe
Copy link

Nice!

@syzer
Copy link

syzer commented Jul 12, 2015

👍

@miniflycn
Copy link

awesome!!

@SerkanSipahi
Copy link

incredible :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment