#361·FastUI

Unexpected state sharing between two forms

Author: elio2tCreated Oct 17, 2024Updated Oct 17, 2024

Description

When switching between two forms without submitting, values from one form persist and are incorrectly shared with the other. As a result, the select field in a form may have a value that is not among its valid options.

https://github.com/user-attachments/assets/b40dc5ed-96cb-4678-b1a3-4ac33f48ccdf

Minimal reproducible example

python
from enum import StrEnum

from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastui import AnyComponent, FastUI, prebuilt_html
from fastui import components as c
from fastui.events import GoToEvent
from pydantic import BaseModel, Field

app = FastAPI()


def _layout(*components: AnyComponent) -> list[AnyComponent]:
    return [
        c.Navbar(
            start_links=[
                c.Link(
                    components=[c.Text(text="Form 1")],
                    on_click=GoToEvent(url="/form1/"),
                    active="startswith:/form1/",
                ),
                c.Link(
                    components=[c.Text(text="Form 2")],
                    on_click=GoToEvent(url="/form2/"),
                    active="startswith:/form2/",
                ),
            ],
        ),
        c.Page(
            components=[
                *components,
            ]
        ),
    ]


class Enum1(StrEnum):
    AAA = "AAA"
    BBB = "BBB"


class Enum2(StrEnum):
    CCC = "CCC"
    DDD = "DDD"


class Form1(BaseModel):
    text1: str = Field()
    select1: Enum1 = Field()


class Form2(BaseModel):
    text2: str = Field()
    select2: Enum2 = Field()


@app.get("/api/form1/", response_model=FastUI, response_model_exclude_none=True)
async def form1() -> list[AnyComponent]:
    return _layout(c.ModelForm(model=Form1, submit_url="."))


@app.get("/api/form2/", response_model=FastUI, response_model_exclude_none=True)
async def form2() -> list[AnyComponent]:
    return _layout(c.ModelForm(model=Form2, submit_url="."))


@app.get("/{path:path}")
async def html_landing() -> HTMLResponse:
    return HTMLResponse(prebuilt_html())

Environment

FastUI version: 0.7.0 Python version: 3.12.4