Forms
These components located in ludic.catalog.forms
are in an experimental mode. There is the possibility to automatically create form fields from annotations, but it is far from production-ready.
Input Field
#The InputField
component is the most basic form field. It is a wrapper around the input
HTML element which also generates a label if not disabled. Here is what it looks like:
from ludic.catalog.forms import InputField InputField( label="First Name", placeholder="Your First Name", name="sample-input-field", )
You can also create the input field without the label by not passing the label
attribute:
from ludic.catalog.forms import InputField InputField( name="sample-input-field", )
Select Field
#The SelectField
component is a wrapper around the select
HTML element. It also generates a label if not disabled. Here is what it looks like:
from ludic.catalog.forms import SelectField, Option SelectField( Option("Option 1"), Option("Option 2", selected=True), Option("Option 3"), label="Select Option", name="sample-select-field", )
Text Area
#The TextAreaField
component is a wrapper around the textarea
HTML element. It also generates a label if not disabled. Here is what it looks like:
from ludic.catalog.forms import TextAreaField TextAreaField( name="sample-text-area", label="Description", )
Similarly as for the input field, you can create the text area without the label.
Choices
#The ChoiceField
component is a wrapper around the <input type='radio'>
HTML element. It also generates a label if not disabled. Here is what it looks like:
Are you a vegetarian?
from ludic.catalog.forms import ChoiceField ChoiceField( name="sample-choice-field", label="Are you a vegetarian?", choices=[("yes", "Yes"), ("no", "No")], selected="no", ),
Form
#The Form
component is a wrapper around the form
HTML element. Here is a sample form:
from ludic.catalog.buttons import ButtonSuccess from ludic.catalog.forms import Form, InputField, TextAreaField from ludic.catalog.layouts import Cluster Form( InputField( name="sample-input-field", label="First Name", placeholder="Your First Name", ), TextAreaField( name="sample-text-area", label="Description", ), Cluster(ButtonSuccess("Submit")), )
We use the Cluster
component to create a form with multiple input fields and buttons. this component is described in the Layouts section. You can also have the input field and the button aligned horizontally using this layout component:
from ludic.catalog.buttons import ButtonSuccess from ludic.catalog.forms import Form, InputField, Option, SelectField from ludic.catalog.layouts import Cluster Form( Cluster( InputField(placeholder="First Name"), SelectField( Option("Age", disabled=True, selected=True), Option("0-18"), Option("18+"), ), ButtonSuccess("Submit"), ) )
Generating Form Fields
#In some cases, the attributes of a component or class-based endpoint can be used to create form fields automatically using the create_fields
function. Here is an example:
from typing import Annotated from ludic.attrs import Attrs from ludic.catalog.forms import FieldMeta, create_fields class PersonAttrs(Attrs): first_name: Annotated[str, FieldMeta()] last_name: Annotated[str, FieldMeta()] person = PersonAttrs(first_name="John", last_name="Doe") fields = create_fields(person, spec=PersonAttrs)
The create_fields
function generates form fields from annotations. It generates only fields that are annotated with the FieldMeta
dataclass, which looks like this:
@dataclass class FieldMeta: label: str | Literal["auto"] | None = "auto" kind: Literal["input", "textarea", "checkbox"] = "input" type: Literal["text", "email", "password", "hidden"] = "text" attrs: InputAttrs | TextAreaAttrs | None = None parser: Callable[[Any], PrimitiveChildren] | None = None
The parser
attribute validates and parses the field. Here is how you would use it:
from typing import Annotated from ludic.attrs import Attrs from ludic.web.parsers import ValidationError from ludic.catalog.forms import FieldMeta def parse_email(email: str) -> str: if len(email.split("@")) != 2: raise ValidationError("Invalid email") return email class CustomerAttrs(Attrs): id: str name: Annotated[ str, FieldMeta(label="Email", parser=parse_email), ]
Fields created with the create_fields
function can be than extracted from submitted form data using the Parser class.