diff --git a/change/@microsoft-fast-element-e173d34b-0061-4c9d-94b5-415929d7dc5e.json b/change/@microsoft-fast-element-e173d34b-0061-4c9d-94b5-415929d7dc5e.json
new file mode 100644
index 00000000000..076ceecae26
--- /dev/null
+++ b/change/@microsoft-fast-element-e173d34b-0061-4c9d-94b5-415929d7dc5e.json
@@ -0,0 +1,7 @@
+{
+ "type": "patch",
+ "comment": "Support element filters for declarative f-children directives.",
+ "packageName": "@microsoft/fast-element",
+ "email": "pradeepramolaa@gmail.com",
+ "dependentChangeType": "none"
+}
diff --git a/packages/fast-element/docs/declarative/syntax.md b/packages/fast-element/docs/declarative/syntax.md
index f2f7fff4b9b..cdfa2058695 100644
--- a/packages/fast-element/docs/declarative/syntax.md
+++ b/packages/fast-element/docs/declarative/syntax.md
@@ -336,6 +336,8 @@ Attribute directives include:
Example:
```html
+
+
```
- **ref**
diff --git a/packages/fast-element/src/declarative/template-parser.ts b/packages/fast-element/src/declarative/template-parser.ts
index 4df9c5e8993..7bf75ebdbf5 100644
--- a/packages/fast-element/src/declarative/template-parser.ts
+++ b/packages/fast-element/src/declarative/template-parser.ts
@@ -45,6 +45,11 @@ interface TemplateResolutionContext {
schema: Schema;
}
+interface NodeDirectiveOptions {
+ property: string;
+ filter?: ReturnType;
+}
+
/**
* Tracks string segments accumulated during template parsing and maintains
* a running concatenation so that `bindingResolver` can receive the full
@@ -232,27 +237,12 @@ export class TemplateParser {
): void {
switch (name) {
case "children": {
- externalValues.push(children(propName));
+ externalValues.push(children(this.resolveNodeDirectiveOptions(propName)));
break;
}
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));
+ externalValues.push(slotted(this.resolveNodeDirectiveOptions(propName)));
break;
}
@@ -264,6 +254,21 @@ export class TemplateParser {
}
}
+ private resolveNodeDirectiveOptions(propName: string): NodeDirectiveOptions {
+ const parts = propName.trim().split(" filter ");
+ const options: NodeDirectiveOptions = {
+ property: parts[0],
+ };
+
+ if (parts[1]?.startsWith("elements(")) {
+ let params = parts[1].replace("elements(", "");
+ params = params.substring(0, params.lastIndexOf(")"));
+ options.filter = elements(params || undefined);
+ }
+
+ return options;
+ }
+
/**
* Resolve an access binding — shared by content bindings, boolean-attribute
* fallback, and default attribute bindings.
diff --git a/packages/fast-element/test/declarative/fixtures/directives/children/children.spec.ts b/packages/fast-element/test/declarative/fixtures/directives/children/children.spec.ts
index d88e1005e96..1dfe6b890e6 100644
--- a/packages/fast-element/test/declarative/fixtures/directives/children/children.spec.ts
+++ b/packages/fast-element/test/declarative/fixtures/directives/children/children.spec.ts
@@ -11,12 +11,29 @@ test.describe("f-template", async () => {
await hydrationCompleted;
const element = page.locator("test-element");
- const listItems = element.locator("li");
+ const listItems = element.locator("[data-testid='list-items'] li");
await expect(listItems).toHaveCount(2);
await expect(listItems).toHaveText(["Foo", "Bar"]);
+ const filteredNodeNames = await element.evaluate(
+ (
+ node: HTMLElement & {
+ allChildren: Node[];
+ filteredChildren: Node[];
+ },
+ ) => ({
+ allChildren: node.allChildren.map(child => child.nodeName),
+ filteredChildren: node.filteredChildren.map(child => child.nodeName),
+ }),
+ );
+
+ expect(filteredNodeNames).toEqual({
+ allChildren: ["LI", "LI"],
+ filteredChildren: ["SPAN"],
+ });
+
await element.evaluate((node: HTMLElement & { list: Array }) => {
node.list = ["A", "B", "C"];
});
@@ -24,5 +41,6 @@ test.describe("f-template", async () => {
await expect(listItems).toHaveCount(3);
await expect(listItems).toHaveText(["A", "B", "C"]);
+ await expect(element).toHaveJSProperty("allChildren.length", 3);
});
});
diff --git a/packages/fast-element/test/declarative/fixtures/directives/children/index.html b/packages/fast-element/test/declarative/fixtures/directives/children/index.html
index bb848854e28..ce4101fb882 100644
--- a/packages/fast-element/test/declarative/fixtures/directives/children/index.html
+++ b/packages/fast-element/test/declarative/fixtures/directives/children/index.html
@@ -5,9 +5,15 @@
-
+
+
+ IncludedText node
-
+
+
+
+ IncludedText node
+
diff --git a/packages/fast-element/test/declarative/fixtures/directives/children/main.ts b/packages/fast-element/test/declarative/fixtures/directives/children/main.ts
index a05c96d1d35..215509ad4c6 100644
--- a/packages/fast-element/test/declarative/fixtures/directives/children/main.ts
+++ b/packages/fast-element/test/declarative/fixtures/directives/children/main.ts
@@ -7,6 +7,12 @@ class TestElement extends FASTElement {
@observable
listItems: Node[] = [];
+ @observable
+ allChildren: Node[] = [];
+
+ @observable
+ filteredChildren: Node[] = [];
+
@observable
list: Array = ["Foo", "Bar"];
}
diff --git a/packages/fast-element/test/declarative/fixtures/directives/children/templates.html b/packages/fast-element/test/declarative/fixtures/directives/children/templates.html
index 52c239daf52..eb214786789 100644
--- a/packages/fast-element/test/declarative/fixtures/directives/children/templates.html
+++ b/packages/fast-element/test/declarative/fixtures/directives/children/templates.html
@@ -1,3 +1,7 @@
-
+
+
+
+ IncludedText node
+