sebastienros/fluid

If a property is not provided, then its value is null / blank. Can we instead keep the 'placeholder'?

Opened this issue · 6 comments

If a property (object/variable) is not provided in the model, then its value is null / blank. Is there some option that would instead keep the 'placeholder' (variable name enclosed in double curly braces)?

E.g., for below example, rather than returning
Temperature Humidity
it would return
Temperature {{intSelected}} Humidity {{intSelected}}

using Fluid;

string feature = "{% for str in stringsSelected %} {{str}} {{intSelected}} {% endfor %}";

List<string> stringsSelected = new() { "Temperature", "Humidity" };
int intSelected = 74;
string FeatureResult;

var parser = new FluidParser();

if (parser.TryParse(feature, out var template, out var error))
{
    //var model = new { stringsSelected, intSelected };
    var model = new { stringsSelected };  //if a property is not provided, then its value is null / blank.  Can we instead keep the 'placeholder'?
    var context = new TemplateContext(model);
    var result = template.Render(context);

    Console.WriteLine(result);
}
else
{
     Console.WriteLine($"Error: {error}");
}

Couldn't you use the default filter? Something like this will produce what you wanted:

{{intSelected | default: "{{intSelected}}"}}

This uses standard liquid template features, even though you have to type "the tag" twice.

Thanks for the prompt reply.

There are two issues with the default filter:

  1. As you mention, 'you have to type "the tag" twice', which is a bit messy. I suppose that for now I could search/replace all {{…}} with {{… | default: "{{…}}"}} in a 'wrapper' / pre-process.

  2. Note that the docs for the default filter say that an “empty” value would also be replaced by default, not just the absence of the property.
    https://shopify.github.io/liquid/filters/default/

In this example, product_price is empty, so the default value is used.
Input
{% assign product_price = "" %}
{{ product_price | default: 2.99 }}
Output

2.99

How can I submit a request that this be considered / make that an ‘optional behavior’ / setting?

Can you try implementing a custom member provider that would return what you want? It's extensible. You could write one that wraps the current implementation.

For the default filter, if you think there is an issue please file a ticket and if possible provide the PR.

I'm not sure what you mean by "custom member provider". Are you referring to Customizing object accessors ? https://github.com/sebastienros/fluid#customizing-object-accessors
However, in my case, it's not for a specific type, it's for all types.

Is it possible to override GetValue as per below. I tried, but the WriteLines don't even get hit.

class ObjectValue : ObjectValueBase
{
    public ObjectValue(object value) : base(value)
    {
    }

    public override ValueTask<FluidValue> GetValueAsync(string name, TemplateContext context)
    {
        Console.WriteLine($"!!!{name}!!!");        
        if (Value == null)
            return StringValue.Create("{{" + name + "}}");

        return NilValue.Instance;        
    }

    protected override FluidValue GetValue(string name, TemplateContext context)
    {
        Console.WriteLine($"!!!{name}!!!");
        if (Value == null)
            return StringValue.Create("{{" + name + "}}");

        return NilValue.Instance;
    }
}

I am also interested in this because its easier for the user to spot errors in their template.

Any news on this topic? I would like to have something like this as well