Skip to content

Inline Editor

The InlineEditor component renders a compact inline display/edit surface for server-driven edit flows.

Quick Start

InlineEditor("username", value="jdoe", editing=False)

Usage Scenarios

Read Mode

InlineEditor("title", value="My Document", display="My Document", editing=False)

Edit Mode

InlineEditor("title", value="My Document", editing=True, endpoint="/update/title")

With Custom Endpoints

InlineEditor(
    "email",
    value="user@example.com",
    editing=False,
    edit_endpoint="/edit/email",
    endpoint="/save/email",
    method="post",
)

Parameter Reference

Parameter Type Default Description
name str Required Input name attribute
value str "" Current value
display Any \| None None Custom display content (falls back to value)
editing bool False Whether to show the edit form
endpoint str \| None None Save endpoint
edit_endpoint str \| None None Endpoint to request edit mode
method "get" \| "post" \| "put" \| "patch" "post" Save method
input_type str "text" HTML input type
save_label str "Save" Save button label
cancel_label str "Cancel" Cancel button label
edit_label str "Edit" Edit button label
hx_target str \| None None HTMX target selector
hx_swap str "outerHTML" HTMX swap style
input_cls str \| None None Additional classes for input
actions_cls str \| None None Additional classes for action buttons
**kwargs Any - Additional HTML attributes

Accessibility

  • Edit button uses variant="link" and size="sm" for unobtrusive styling.
  • Input gets aria-label derived from the field name.
  • Proper focus management is handled by HTMX swaps.

API Reference

faststrap.components.forms.inline_editor.InlineEditor(name, value='', *, display=None, editing=False, endpoint=None, edit_endpoint=None, method='post', input_type='text', save_label='Save', cancel_label='Cancel', edit_label='Edit', hx_target=None, hx_swap='outerHTML', input_cls=None, actions_cls=None, **kwargs)

Render a compact inline display/edit surface.

Apps can render editing=False for the read view and return editing=True from an HTMX endpoint for the edit view.

Source code in src/faststrap/components/forms/inline_editor.py
@register(category="forms")
@stable
def InlineEditor(
    name: str,
    value: str = "",
    *,
    display: Any | None = None,
    editing: bool = False,
    endpoint: str | None = None,
    edit_endpoint: str | None = None,
    method: InlineEditorMethod = "post",
    input_type: str = "text",
    save_label: str = "Save",
    cancel_label: str = "Cancel",
    edit_label: str = "Edit",
    hx_target: str | None = None,
    hx_swap: str = "outerHTML",
    input_cls: str | None = None,
    actions_cls: str | None = None,
    **kwargs: Any,
) -> Div:
    """Render a compact inline display/edit surface.

    Apps can render `editing=False` for the read view and return
    `editing=True` from an HTMX endpoint for the edit view.
    """
    if method not in {"get", "post", "put", "patch"}:
        msg = f"method must be one of get, post, put, patch; got {method!r}"
        raise ValueError(msg)

    user_cls = kwargs.pop("cls", "")
    attrs: dict[str, Any] = {
        "cls": merge_classes(
            "faststrap-inline-editor d-inline-flex align-items-center gap-2", user_cls
        ),
        "data_fs_inline_editor": "true",
    }
    attrs.update(convert_attrs(kwargs))

    target = hx_target
    if target is None and attrs.get("id"):
        target = f"#{attrs['id']}"

    if not editing:
        edit_attrs: dict[str, Any] = {}
        if edit_endpoint:
            edit_attrs["hx_get"] = edit_endpoint
            if target:
                edit_attrs["hx_target"] = target
            edit_attrs["hx_swap"] = hx_swap

        return Div(
            Span(display if display is not None else value, cls="faststrap-inline-editor-value"),
            Button(edit_label, variant="link", size="sm", cls="p-0", **edit_attrs),
            **attrs,
        )

    form_attrs: dict[str, Any] = {
        "method": method,
        "cls": "d-inline-flex align-items-center gap-2",
    }
    if endpoint:
        form_attrs["action"] = endpoint
        form_attrs[f"hx_{method}"] = endpoint
        if target:
            form_attrs["hx_target"] = target
        form_attrs["hx_swap"] = hx_swap

    input_attrs = {
        "type": input_type,
        "name": name,
        "value": value,
        "cls": merge_classes("form-control form-control-sm", input_cls),
        "aria_label": f"Edit {name}",
    }

    actions = Div(
        Button(save_label, type="submit", variant="primary", size="sm"),
        Button(cancel_label, type="button", variant="secondary", outline=True, size="sm"),
        cls=merge_classes("d-inline-flex gap-2", actions_cls),
    )

    return Div(FTForm(FTInput(**input_attrs), actions, **convert_attrs(form_attrs)), **attrs)