Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mustache: Check for variable in current context only

I'm using the Mustache template engine in a project, and I've run in to an issue where I have the same attribute name in different contexts, and I'm wondering if there is a way to specify only the attribute from the local context, without changing the name of the attribute.

Consider having this data:

{
   title: 'Hello World',
   href: 'http://example.com',
   socials: [
      {
         label: 'Twitter',
         href: 'http://twitter.com'
      },
      {
         label: 'Facebook',
      }
   ]
}

The issue here is that the href attribute is available in two different contexts which will cause problems if you try to use this conditionally, like this:

<div>
   <h1>{{title}}</h1>
   <a href="{{href}}">{{href}}</a>
   <ul>
      {{#socials}}
         <li>
            {{#href}}
               <!--- In here http://twitter.com will be used for the first Social,
               but for Facebook it will use http://example.com.
               For Facebook, this value should be empty. --->

               <a href="{{href}}">{{label}}</a>
            {{/href}}

            {{^href}}
               <!--- This will never be rendered --->
               {{label}}               
            {{/href}}
         </li>
      {{/socials}}
   </ul>
</div>

Hopefully this demonstrates my issue. What I want is to check ONLY the current context for the variable, not check the parent context as well.

I know I can use {{.}} to access the current context, but is there a way to access a specific variable in the current context? For example, {{.href}} (which I have tried, but does not work...)

like image 438
E-g Avatar asked Jun 12 '26 14:06

E-g


2 Answers

There is a closed issue about this in the mustache.js repo in GitHub. The consensus there is that it is not supported and likely won't be implemented.

Seems like renaming href may be your best option. (See somewhat related discussion on this other GitHub issue).

like image 177
kimbo Avatar answered Jun 14 '26 04:06

kimbo


The answer by kimbo is correct: renaming href, either in the top-level object or in the objects nested within socials (but not both), is one way in which you can change the data in order to solve the problem. For completeness, I will mention two other possibilities which are about equally good/bad:

  1. Add a falsy href attribute everywhere it is unset.
{
   title: 'Hello World',
   href: 'http://example.com',
   socials: [
      {
         label: 'Twitter',
         href: 'http://twitter.com'
      },
      {
         label: 'Facebook',
         href: undefined
      }
   ]
}
  1. Wrap the top-level properties so the socials do not fall back to them. This would require adjustments in the template as well, for example {{top.title}} instead of just {{title}}.
{
   top: {
       title: 'Hello World',
       href: 'http://example.com',
   },
   socials: [
      {
         label: 'Twitter',
         href: 'http://twitter.com'
      },
      {
         label: 'Facebook',
      }
   ]
}

This is admittedly an area where Mustache is currently lacking. Power lambdas would allow for a masking operator that ensures only the top scope is visible, so we could do something like this instead:

<div>
   <h1>{{title}}</h1>
   <a href="{{href}}">{{href}}</a>
   <ul>
      {{#socials}}
         <li>
            {{#mask.href}}
               <a href="{{mask.href}}">{{label}}</a>
            {{/mask.href}}
            {{^mask.href}}
               {{label}}               
            {{/mask.href}}
         </li>
      {{/socials}}
   </ul>
</div>
like image 39
Julian Avatar answered Jun 14 '26 06:06

Julian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!