feat: asked-field envelope, standalone form components, branched forms
This commit is contained in:
parent
0d43b0e8fb
commit
f27be044b4
26 changed files with 3651 additions and 104 deletions
|
|
@ -105,6 +105,68 @@ See `backend/flows/bauvorhaben.json` for a full 4-level example
|
|||
(Gebäude → Bestandteil → Maßnahme → Gussjahr, plus sibling branch and
|
||||
bool trigger).
|
||||
|
||||
## User-built form components (no kirche base needed)
|
||||
|
||||
A plain `CustomComponent` whose display name ends with `"Form"` is also
|
||||
parsed into a web form — same template contract, no base class. To make
|
||||
submitted values reach it at runtime, add an envelope input and merge it
|
||||
in the output method (pattern):
|
||||
|
||||
```python
|
||||
from lfx.io import MessageTextInput # add to imports
|
||||
import json
|
||||
|
||||
# add to inputs:
|
||||
MessageTextInput(name="form_values", display_name="Form values", value="", show=False)
|
||||
|
||||
# at the top of the output method:
|
||||
try:
|
||||
raw = self.form_values.text if hasattr(self.form_values, "text") else self.form_values
|
||||
submitted = json.loads(raw or "{}")
|
||||
except Exception:
|
||||
submitted = {}
|
||||
if isinstance(submitted.get("payload"), dict):
|
||||
submitted = submitted["payload"]
|
||||
|
||||
|
||||
def val(name, default):
|
||||
return submitted.get(name, default)
|
||||
```
|
||||
|
||||
Then use `val("rolle", self.rolle)` etc., and wire a `ChatInput` node
|
||||
into `form_values` on the canvas. Branch markers (`[visible_if ...]`
|
||||
in `info`) work here too — the parser reads the template only.
|
||||
|
||||
## Asked fields only (run envelope `fields`)
|
||||
|
||||
The API sends the asked field names (from the version's form schema)
|
||||
in the run envelope's `fields` list. `collect()` then emits defaults
|
||||
only for asked AND currently visible fields (branch conditions are
|
||||
evaluated against submitted values over code defaults, so hidden
|
||||
fields stay out exactly as the frontend never submits them): the
|
||||
template may declare fields unknown to this code (they arrive via
|
||||
envelope and merge normally), and unasked code defaults stay out of
|
||||
the output. Without the list — raw dicts, Langflow playground — all
|
||||
visible declared defaults apply as before.
|
||||
|
||||
## Variant flows (own component per flow)
|
||||
|
||||
A flow whose fields differ from `CustomInputForm` gets its own
|
||||
standalone component (see `bauvorhaven_form.py` → "Bauvorhaben Form"
|
||||
in the palette): same class pattern, own `inputs` list. Standalone
|
||||
means it: no imports between form modules — the LFX runtime executes
|
||||
the embedded module source without our `kirche` package, so every form
|
||||
component must be self-contained (stdlib + `lfx` only). Copy the file
|
||||
as the starting point for future forms.
|
||||
|
||||
Rule: code-declared inputs must equal template fields
|
||||
(`test_embedded_code_matches_template_fields` enforces it; required
|
||||
Multiselect uses the `[" "]` sentinel). Generate node + flow with
|
||||
`kirche_node(..., component_cls, code_override)` and
|
||||
`build_bauvorhaben()` in `backend/scripts/make_flow_fixtures.py`
|
||||
rather than hand-editing JSON. Restart Langflow afterwards so the
|
||||
palette picks up the new component, then build/upload the flow.
|
||||
|
||||
## Output type: Data (JSON), not Message
|
||||
|
||||
`collect()` returns `Data(data={...})` — a real JSON object. Consequences:
|
||||
|
|
@ -119,7 +181,8 @@ bool trigger).
|
|||
- `required=True` on a template field: `lfx validate --level 4` demands a
|
||||
value or an edge, so the canonical-flow generator
|
||||
(`backend/scripts/make_flow_fixtures.py`) writes a single-space
|
||||
sentinel value for such fields. The form parser treats whitespace-only
|
||||
sentinel value for such fields (`[" "]` for Multiselect, which rejects
|
||||
a plain string at runtime). The form parser treats whitespace-only
|
||||
values as "no default" — don't ship real whitespace defaults.
|
||||
- Field key = `name` (stable, freely renamable but must stay unique and
|
||||
non-empty; collisions get a `_2`/`_3` suffix in the form schema);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue