each with condition
gstrit opened this issue · comments
Hello,
I would like to write a each block helper with one condition. Exactly like that : https://stackoverflow.com/questions/41790849/how-do-i-filter-this-array-using-value-with-handlebars-js
The goal is to have the @last correct.
Thanks for your help.
Hello @gstrit
What is the problem you're facing?
Share the code you currently have and I'd be able to assist with modifying it.
Hello @zjklee
_handlebars.RegisterHelper("each_when", (writer, options, context, arguments) =>
{
var enumerable = (IEnumerable)arguments[0];
var property = (string)arguments[1];
var value = (string)arguments[2];
var enumerator = enumerable.GetEnumerator();
while(enumerator.MoveNext()) {
if(enumerator.Current.property == value) //here I should be able to check if the property has the good value
options.Template(writer, enumerator.Current);
}
});
I don't know how to dynamically check the value and I don't know how to set @FIRST and @last fields with the good values.
@FIRST and @last should be set according the filter. If the first value of the list doesn't match the property and its value, it should not be assigned to the @FIRST field.
Edit note: fixed code block (@zjklee)
@gstrit , should be something like this (I haven't tested it though):
handlebars.RegisterHelper("each_when", (writer, options, context, arguments) =>
{
var target = (IEnumerable)arguments[0];
var property = (string)arguments[1];
var value = (string)arguments[2];
using var frame = options.CreateFrame();
var iterator = new IteratorValues(frame);
var blockParamsValues = new BlockParamsValues(frame, options.BlockVariables);
blockParamsValues.CreateProperty(0, out var _0);
blockParamsValues.CreateProperty(1, out var _1);
var enumerator = ExtendedEnumerator<object>.Create(target.GetEnumerator());
iterator.First = BoxedValues.True;
iterator.Last = BoxedValues.False;
var index = 0;
var executed = false;
while(enumerator.MoveNext())
{
var current = enumerator.Current;
var instance = current.Value;
if (
!options.TryAccessMember(instance, property, out var v)
|| v.ToString() != value
){ continue; }
executed = true;
var indexObject = BoxedValues.Int(index);
if (index == 1) iterator.First = BoxedValues.False;
if (current.IsLast) iterator.Last = BoxedValues.True;
iterator.Key = iterator.Index = indexObject;
blockParamsValues[_0] = value;
blockParamsValues[_1] = indexObject;
iterator.Value = value;
frame.Value = value;
options.Template(writer, frame);
++index;
}
if (!executed)
{
options.Template(writer, context);
}
});
@gstrit , alternative approach:
handlebars.RegisterHelper("each_when", (writer, options, context, arguments) =>
{
var property = (string)arguments[1];
var value = arguments[2];
var target = ((IEnumerable)arguments[0])
.OfType<object>()
.Where(o => options.TryAccessMember(o, property, out var v) && v.Equals(value));
if (!ObjectDescriptor.TryCreate(target, out var descriptor))
{
options.Inverse(writer, context);
return;
}
descriptor.Iterator.Iterate(writer, options.Frame, options.BlockVariables, target, options.Template, options.Inverse);
});