Summary
To implement a dependent autocomplete (e.g. Jira project → issue type → user) in a consumer app, we currently ship four small patches to @flowdrop/flowdrop@1.2.2 in the flowdrop-rs frontend. None of the four are present in 1.12.0. This issue proposes them as upstream API extensions so we can drop our patch file.
Issue #28 already proposes solving the dependent-autocomplete use case by adding a params field to AutocompleteConfig directly inside FormAutocomplete. The four extensions below are an orthogonal route: they let consumers register their own dependent-aware component via the field registry, wrapping the built-in FormAutocomplete. Either approach solves the user-facing problem — these extensions are useful for any custom field component that needs sibling form-state, not just dependent autocomplete, so they would still be valuable even if #28 lands.
Use case
In flowdrop-rs the Jira node has these autocomplete fields:
account (selects a Jira account secret)
project (needs the chosen account to authenticate)
issue_type (needs account + project)
assignee (needs account + project + a query)
Backend endpoints expect the parent field values as query parameters:
GET /api/flowdrop/jira/issue-types?account={account}&project={project}
The standard FormAutocomplete only appends the search term, so we register a custom component that:
- Reads the sibling values out of the form state via Svelte context.
- Builds a derived
AutocompleteConfig whose url already carries the dependency query params.
- Forwards everything to the built-in
FormAutocomplete.
To make that work, four pieces of the public API need small tweaks.
Requested changes
1. Expose form values via Svelte context — ConfigForm.svelte
Add a flowdrop:getFormValues context alongside the existing flowdrop:getAuthProvider:
setContext<() => AuthProvider | undefined>(
"flowdrop:getAuthProvider",
() => authProvider,
);
+ setContext<() => Record<string, unknown>>(
+ "flowdrop:getFormValues",
+ () => configValues,
+ );
Why: Without this, a registered field component has no general-purpose way to observe sibling values reactively. This is the only piece that requires source from ConfigForm, and it's useful for any cross-field component (not just autocomplete).
2. Consult fieldComponentRegistry for autocomplete fields — FormField.svelte
FormFieldLight already routes autocomplete fields through the registry (per the original work behind #11). The heavier FormField does not — it always falls through to the built-in FormAutocomplete. Mirror the registry consultation there:
+ import { fieldComponentRegistry } from "../../form/fieldRegistry.js";
...
+ const registeredComponent = $derived(
+ fieldComponentRegistry.resolveFieldComponent(schema),
+ );
...
+ {:else if fieldType === "autocomplete" && schema.autocomplete && registeredComponent}
+ <registeredComponent.component
+ id={fieldKey}
+ value={autocompleteValue}
+ autocomplete={schema.autocomplete}
+ dependencies={schema.dependencies}
+ placeholder={schema.placeholder ?? ""}
+ {required}
+ ariaDescribedBy={descriptionId}
+ disabled={isReadOnly}
+ onChange={(val) => onChange(val)}
+ />
{:else if fieldType === "autocomplete" && schema.autocomplete}
<FormAutocomplete ... />
Why: Consumers that use FormField (the rich variant) cannot currently override autocomplete with a registered component.
3. Pass autocomplete + dependencies to registered components — FormFieldLight.svelte
The registered-component invocation in FormFieldLight does not forward autocomplete or dependencies:
<registeredComponent.component
...
variables={schema.variables}
placeholderExample={schema.placeholderExample as string | undefined}
+ autocomplete={schema.autocomplete}
+ dependencies={schema.dependencies}
onChange={(val: unknown) => onChange(val)}
/>
Why: Without this a registered autocomplete component has no idea what URL to fetch from. Closely related to #11, but the autocomplete-config plumbing wasn't applied to this registered branch.
4. Export FormAutocomplete as a subpath — package.json
"./form": {
"types": "./dist/form/index.d.ts",
"svelte": "./dist/form/index.js",
"default": "./dist/form/index.js"
},
+ "./form/autocomplete": {
+ "types": "./dist/components/form/FormAutocomplete.svelte.d.ts",
+ "svelte": "./dist/components/form/FormAutocomplete.svelte",
+ "default": "./dist/components/form/FormAutocomplete.svelte"
+ },
"./form/code": { ... },
Why: The whole point of (1)–(3) is to let a consumer wrap FormAutocomplete rather than reimplement type-ahead, debouncing, label caching, etc. Without a public export there is no supported way to import it.
Schema shape consumers would use
These changes accept (but do not interpret) a dependencies map on the field schema:
{
"type": "string",
"format": "autocomplete",
"autocomplete": { "url": "/api/jira/issue-types", "fetchOnFocus": true },
"dependencies": { "account": "account", "project": "project" }
}
Mapping: URL query-param name → sibling field name. The registered component resolves dependency values via getContext('flowdrop:getFormValues') and appends them to the URL.
Reference implementation
The dependent-autocomplete wrapper we ship (FormDependentAutocomplete.svelte, ~170 LOC) is happy to be contributed back if helpful, but the proposal here is just the four small API hooks — consumers can supply their own component logic.
Test plan / impact
- All four changes are additive: no existing prop, export, or context is removed or renamed.
- Existing consumers that don't register a custom autocomplete component get unchanged behaviour (the new
{:else if … && registeredComponent} branch only activates when something is registered).
- (1) is a new context only — uncontextual consumers ignore it.
- (4) is a new subpath only —
./form etc. are unchanged.
Related
Summary
To implement a dependent autocomplete (e.g. Jira project → issue type → user) in a consumer app, we currently ship four small patches to
@flowdrop/flowdrop@1.2.2in theflowdrop-rsfrontend. None of the four are present in1.12.0. This issue proposes them as upstream API extensions so we can drop our patch file.Issue #28 already proposes solving the dependent-autocomplete use case by adding a
paramsfield toAutocompleteConfigdirectly insideFormAutocomplete. The four extensions below are an orthogonal route: they let consumers register their own dependent-aware component via the field registry, wrapping the built-inFormAutocomplete. Either approach solves the user-facing problem — these extensions are useful for any custom field component that needs sibling form-state, not just dependent autocomplete, so they would still be valuable even if #28 lands.Use case
In flowdrop-rs the Jira node has these autocomplete fields:
account(selects a Jira account secret)project(needs the chosenaccountto authenticate)issue_type(needsaccount+project)assignee(needsaccount+project+ a query)Backend endpoints expect the parent field values as query parameters:
The standard
FormAutocompleteonly appends the search term, so we register a custom component that:AutocompleteConfigwhoseurlalready carries the dependency query params.FormAutocomplete.To make that work, four pieces of the public API need small tweaks.
Requested changes
1. Expose form values via Svelte context —
ConfigForm.svelteAdd a
flowdrop:getFormValuescontext alongside the existingflowdrop:getAuthProvider:setContext<() => AuthProvider | undefined>( "flowdrop:getAuthProvider", () => authProvider, ); + setContext<() => Record<string, unknown>>( + "flowdrop:getFormValues", + () => configValues, + );Why: Without this, a registered field component has no general-purpose way to observe sibling values reactively. This is the only piece that requires source from
ConfigForm, and it's useful for any cross-field component (not just autocomplete).2. Consult
fieldComponentRegistryfor autocomplete fields —FormField.svelteFormFieldLightalready routes autocomplete fields through the registry (per the original work behind #11). The heavierFormFielddoes not — it always falls through to the built-inFormAutocomplete. Mirror the registry consultation there:Why: Consumers that use
FormField(the rich variant) cannot currently override autocomplete with a registered component.3. Pass
autocomplete+dependenciesto registered components —FormFieldLight.svelteThe registered-component invocation in
FormFieldLightdoes not forwardautocompleteordependencies:<registeredComponent.component ... variables={schema.variables} placeholderExample={schema.placeholderExample as string | undefined} + autocomplete={schema.autocomplete} + dependencies={schema.dependencies} onChange={(val: unknown) => onChange(val)} />Why: Without this a registered autocomplete component has no idea what URL to fetch from. Closely related to #11, but the autocomplete-config plumbing wasn't applied to this registered branch.
4. Export
FormAutocompleteas a subpath —package.json"./form": { "types": "./dist/form/index.d.ts", "svelte": "./dist/form/index.js", "default": "./dist/form/index.js" }, + "./form/autocomplete": { + "types": "./dist/components/form/FormAutocomplete.svelte.d.ts", + "svelte": "./dist/components/form/FormAutocomplete.svelte", + "default": "./dist/components/form/FormAutocomplete.svelte" + }, "./form/code": { ... },Why: The whole point of (1)–(3) is to let a consumer wrap
FormAutocompleterather than reimplement type-ahead, debouncing, label caching, etc. Without a public export there is no supported way to import it.Schema shape consumers would use
These changes accept (but do not interpret) a
dependenciesmap on the field schema:{ "type": "string", "format": "autocomplete", "autocomplete": { "url": "/api/jira/issue-types", "fetchOnFocus": true }, "dependencies": { "account": "account", "project": "project" } }Mapping: URL query-param name → sibling field name. The registered component resolves dependency values via
getContext('flowdrop:getFormValues')and appends them to the URL.Reference implementation
The dependent-autocomplete wrapper we ship (
FormDependentAutocomplete.svelte, ~170 LOC) is happy to be contributed back if helpful, but the proposal here is just the four small API hooks — consumers can supply their own component logic.Test plan / impact
{:else if … && registeredComponent}branch only activates when something is registered)../formetc. are unchanged.Related
paramsonAutocompleteConfig)FormFieldLightbut didn't reach the registered-component branch.