Skip to content

fix: support filters for f-children in declarative templates #7631

Description

🐛 Bug Report

f-children in FAST declarative templates does not parse the filter elements(...) syntax, even though the runtime children() directive supports filter through ChildrenDirectiveOptions / NodeBehaviorOptions. This creates an inconsistency between runtime FAST directives and declarative <f-template> syntax.

💻 Repro or Code Sample

Given a declarative template using f-children with an element filter:

<f-template name="test-element">
    <template>
        <ul f-children="{childItems filter elements()}">
            <li>One</li>
            Text node
            <li>Two</li>
        </ul>
    </template>
</f-template>

or with a selector:

<f-template name="test-element">
    <template>
        <ul f-children="{childItems filter elements(li)}">
            <li>One</li>
            <span>Ignored</span>
            <li>Two</li>
        </ul>
    </template>
</f-template>

The declarative parser currently handles filter elements(...) only for f-slotted:

case "slotted": {
    const parts = propName.trim().split(" filter ");
    const slottedOption = {
        property: parts[0],
    };

    if (parts[1]) {
        if (parts[1].startsWith("elements(")) {
            let params = parts[1].replace("elements(", "");
            params = params.substring(0, params.lastIndexOf(")"));
            Object.assign(slottedOption, {
                filter: elements(params || undefined),
            });
        }
    }

    externalValues.push(slotted(slottedOption));
    break;
}

but f-children passes the full string directly as the property name:

case "children": {
    externalValues.push(children(propName));
    break;
}

🤔 Expected Behavior

f-children should support the same filter elements(...) declarative syntax as f-slotted, because the runtime children() directive supports filters through ChildrenDirectiveOptions, which extends NodeBehaviorOptions.

Expected examples:

<ul f-children="{childItems filter elements()}"></ul>
<ul f-children="{childItems filter elements(li)}"></ul>

These should resolve to runtime directive options equivalent to:

children({
    property: "childItems",
    filter: elements(),
});

and:

children({
    property: "childItems",
    filter: elements("li"),
});

😯 Current Behavior

f-children="{childItems filter elements()}" is parsed as:

children("childItems filter elements()")

That means the source property becomes the literal string "childItems filter elements()" instead of "childItems", and no filter is applied.

This differs from f-slotted, where the same filter elements(...) syntax is parsed into an options object with property and filter.

💁 Possible Solution

Share the existing filter elements(...) parsing path between f-slotted and f-children in TemplateParser.resolveAttributeDirective().

For example, parse the directive value once into:

{
    property: string;
    filter?: ElementsFilter;
}

Then use that parsed option for both supported directives:

case "children": {
    externalValues.push(children(parsedOption));
    break;
}

case "slotted": {
    externalValues.push(slotted(parsedOption));
    break;
}

Add declarative fixture coverage for:

<ul f-children="{childItems filter elements()}"></ul>
<ul f-children="{childItems filter elements(li)}"></ul>

and update declarative syntax docs if this is intended to be supported.

🔦 Context

This came up while generating declarative <f-template> HTML from compiled FAST templates. Runtime children({ property, filter: elements(...) }) is representable in FAST Element, but there is no equivalent declarative syntax path because f-children does not parse filters.

Related issue found during search:

🌍 Your Environment

  • OS & Device: macOS
  • Browser: Not browser-specific; affects FAST Element declarative template parsing
  • Version: @microsoft/fast-element 3.0.1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions