Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mustache js takes parent's object scope when none is found in the current one

According to the mustache RFC

A {{name}} tag in a basic template will try to find the name key in the current context. If there is no name key, nothing will be rendered.

I therefore expected this:

var template = '{{#anArray}}{{aString}}{{/anArray}}';

var json = {
    "aString":"ABC",
    "anArray": [1,{"aString":"DEF"}]
 };

To give me once rendered:

"DEF"

However mustache.js looks for values in the parent's scope. Which gives me

"ABCDEF"

Do the context actually means including all the parents scopes ?

http://jsfiddle.net/ZG4zd/20/

like image 931
Flavien Volken Avatar asked Dec 27 '12 11:12

Flavien Volken


People also ask

How does mustache JS work?

It works by expanding tags in a template using values provided in a hash or object. We call it "logic-less" because there are no if statements, else clauses, or for loops. Instead there are only tags. Some tags are replaced with a value, some nothing, and others a series of values.

What are Mustache files?

Mustache is a logic-less templating system. It permits you to use pre-written text files with placeholders that will be replaced at run-time with values particular to a given request.

What is Mustache in HTML?

A Mustache tag begins with two opening braces ( {{ ) and ends with two closing braces ( }} ). As you might have guessed, the {{ and }} delimiters are where Mustache gets its name from!


1 Answers

Short answer: yes.

A bit longer answer. Context.prototype.lookup does a while loop, looking up a token in current context and it's parent contexts, while there is a parent context.

Relevant bit of code:

Context.prototype.lookup = function (name) {
    var value = this._cache[name];

    if (!value) {
      if (name === ".") {
        value = this.view;
      } else {
        var context = this;

        //Iterate ancestor contexts
        while (context) {
          if (name.indexOf(".") > 0) {
            var names = name.split("."), i = 0;

            value = context.view;

            while (value && i < names.length) {
              value = value[names[i++]];
            }
          } else {
            value = context.view[name];
          }

          if (value != null) {
            break;
          }


          context = context.parent;
        }
      }

      this._cache[name] = value;
    }

    if (typeof value === "function") {
      value = value.call(this.view);
    }

    return value;
  };
like image 158
soulcheck Avatar answered Nov 30 '22 12:11

soulcheck