Search code examples
template-enginedust.js

How to handle default value as partial parameters in dust.js?


I actually made a simple dust partial and I would like to give it some parameters with default value. Not very easy to explain but here is a simple example:


Partials

partials/hello.dust

{?label}{label}{:else}Hello{/label}: 
<span>{?name}{name}{:else}World{/name}</span>

partials/hello2.dust

{>"partials/hello"/} and 
{>"partials/hello" label="{label2}" name="{name2}"/}</div>

Examples of how it should work

test_0.dust

{>"partials/hello2" label="Peter" name="Parker" label2="Clark" name2="Kent"/}

Returns: "Peter:Parker and Clark:Kent"

test_1.dust

{>"partials/hello2" label2="Clark" name2="Kent"/}

Returns: "Hello:World and Clark:Kent"

test_2.dust

{>"partials/hello2" label="Peter" name="Parker"/}

Returns: "Peter:Parker and Hello:World"

test_3.dust

{>"partials/hello2"/}

Returns: "Hello:World and Hello:World"


In partials/hello.dust, if label & name variables are not defined, they are replaced with default values (respectively "Hello" and "World")

So here, test_0.dust and test_1.dust will work since I provide label2 and name2 parameters.

In partials/hello2.dust, I don't know if this is possible to do this an elegant way but I would like a different default value for label2 and name2 variables so it is not mandatory to provide them either ("Hello2" and "World2" for example).

One solution I can think of would be to handle all possible combinations in hello2.dust including the partial accordingly (i.e. label2 empty and name2 empty, label2 empty and name2 not empty, label2 not empty and name2 empty, label2 not empty and name2 not empty) but it can be pretty painful and ugly as you can see.

To be clear I would like to be able to do something like this:

partials/hello2.dust

{>"partials/hello"/}
{>"partials/hello" label="{?label2}{label2}{:else}Hello2{/label2}" name="{?name2}{name2}{:else}World2{/name2}"/}


SOLUTION

In case it would help someone, I finally made my own dust helper:

'use strict';

module.exports = function (dust) {
    dust.helpers.default = function (chunk, ctx, bodies, params) {
        var resData, paramVals = {}, saveData = chunk.data;

        var localCtx = ctx;
        if (params) {
            localCtx = ctx.push(params);
        }
        for (var key in bodies) {
            if (key !== 'block') {
                chunk.data = [];
                resData = bodies[key](chunk, localCtx).data.join('');
                if (typeof ctx.get(key) === 'undefined') {
                    paramVals[key] = resData;
                }
            }
        }
        chunk.data = saveData;
        return bodies.block(chunk, localCtx.push(paramVals));
    };
};

So, it can be used like this:

{@default}
{>"partials/mypartialusingname1"/}
hello {name1} & {name2} 
{:name1}Chuck Norris
{:name2}Walter White
{/default}

Then, if name1 and name2 does not exist in the current context it is replaced by some default values.


Solution

  • Dust does not include a facility for setting default values for a context.

    This would be a job for a Dust helper. A naïve version of this helper might look like this:

    Template

    {@defaultParam key="hello" value="moo"/}
    {@defaultParam key="world" value="world"/}
    {hello} {world}
    

    Context

    {
        "hello": "hello"
    }
    

    Helper

    dust.helpers.defaultParam = function(chunk, context, bodies, params) {
      var key = params.key,
          value = params.value;
    
      if(typeof context.get(key) === 'undefined') {
        context.global[key] = value;
      }
    };