Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/npm-fastui/src/components/FormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface FormFieldInputProps extends FormFieldInput {
}

export const FormFieldInputComp: FC<FormFieldInputProps> = (props) => {
const { name, placeholder, required, htmlType, locked, autocomplete } = props
const { name, placeholder, required, htmlType, locked, autocomplete, step } = props

return (
<div className={useClassName(props)}>
Expand All @@ -39,6 +39,7 @@ export const FormFieldInputComp: FC<FormFieldInputProps> = (props) => {
disabled={locked}
placeholder={placeholder}
autoComplete={autocomplete}
step={step}
aria-describedby={descId(props)}
/>
<ErrorDescription {...props} />
Expand Down
1 change: 1 addition & 0 deletions src/npm-fastui/src/models.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ export interface FormFieldInput {
initial?: string | number
placeholder?: string
autocomplete?: string
step?: number | 'any'
type: 'FormFieldInput'
}
export interface FormFieldTextarea {
Expand Down
1 change: 1 addition & 0 deletions src/python-fastui/fastui/components/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class FormFieldInput(BaseFormField):
initial: _t.Union[str, float, None] = None
placeholder: _t.Union[str, None] = None
autocomplete: _t.Union[str, None] = None
step: _t.Union[float, _t.Literal['any'], None] = None
type: _t.Literal['FormFieldInput'] = 'FormFieldInput'


Expand Down
9 changes: 9 additions & 0 deletions src/python-fastui/fastui/json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ def json_schema_field_to_field(
initial=schema.get('default'),
autocomplete=schema.get('autocomplete'),
description=schema.get('description'),
step=schema.get('step', get_default_step(schema)),
)


Expand Down Expand Up @@ -372,6 +373,14 @@ def input_html_type(schema: JsonSchemaField) -> InputHtmlType:
raise ValueError(f'Unknown schema: {schema}') from e


def get_default_step(schema: JsonSchemaField) -> _t.Union[_t.Literal['any'], None]:
key = schema['type']
if key == 'integer':
return None
if key == 'number':
return 'any'


def schema_is_field(schema: JsonSchemaConcrete) -> _ta.TypeGuard[JsonSchemaField]:
"""
Determine if a schema is a field `JsonSchemaField`
Expand Down
34 changes: 34 additions & 0 deletions src/python-fastui/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,3 +469,37 @@ def test_form_textarea_form_fields():
}
],
}


class FormNumbersDefaultStep(BaseModel):
size: int
cost: float


def test_form_numbers_default_step():
m = components.ModelForm(model=FormNumbersDefaultStep, submit_url='/foobar')

assert m.model_dump(by_alias=True, exclude_none=True) == {
'submitUrl': '/foobar',
'method': 'POST',
'type': 'ModelForm',
'formFields': [
{
'name': 'size',
'title': ['Size'],
'required': True,
'locked': False,
'htmlType': 'number',
'type': 'FormFieldInput',
},
{
'name': 'cost',
'title': ['Cost'],
'required': True,
'locked': False,
'htmlType': 'number',
'step': 'any',
'type': 'FormFieldInput',
},
],
}