Templates and flag enum TemplateFilter

It looks like when I have an flags enum in a model, only the last value is passed to a template filter

public enum Options {
  None    = 0,
  Option1 = 1,
  Option2 = 1 << 1. 
  Option3 = 1 << 2.
}

public class EnumFilter : TemplateFilter {
  public bool hasFlag(Options source, Options value) => source.Is(value);
}

and in a view

{{ options | htmlDump }} // outputs: Option1,Option2
{{ hasFlag(options,  "Option1") }}  //outputs:  false

You should use source.Has(value) or .NET’s intrinsic source.HasFlag(value) (more performant) to check for enum flags, Is does an exact (i.e. ==) match.

As this is useful I’ve added new generic hasFlag and isEnum default filters which you can use for different enum types that lets you use either the string value, Enum value or Enum’s integer value, e.g:

Given Enum and args:

public enum Options {
  None    = 0,
  Option1 = 1,
  Option2 = 2, //= 1 << 1
  Option4 = 4, //=1 << 2
}

Args = {
    ["options0"] = Options.None,
    ["options1"] = Options.Option1,
    ["options2"] = Options.Option2,
    ["options4"] = Options.Option4,
    ["options3"] = (Options.Option1 | Options.Option2)
}

Will all return true:

{{hasFlag(options3, 'Option1') && hasFlag(options3, 1) && hasFlag(options3,options1)&& 
   isEnum(options1, 'Option1') && isEnum(options1, 1)  && isEnum(options1, options1) }}

While these all return false:

{{ hasFlag(options3, 'Option4') || hasFlag(options3, 4) || hasFlag(options3, options4)
    isEnum(options3, 'Option1') || isEnum(options3, 1)  || isEnum(options3, options1) }}

These new filters is available from the latest v5.4.1 that’s now available on MyGet.

If you do upgrade to the latest v5.4.1 please be aware of the breaking default change to Request Input Params.

1 Like

Thanks @mythz works a treat :+1: