Basic Form
A basic form example using hakumi_form_with with text fields, password, and textarea.
Code
<%= hakumi_form_with(url: "/demo", method: :post, html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :basic_username,
label: "Username",
caption: "Enter your unique username",
placeholder: "username",
required: true %>
<%= f.text_field :basic_email,
label: "Email",
caption: "We'll never share your email",
placeholder: "email@example.com",
required: true %>
<%= f.password_field :basic_password,
label: "Password",
caption: "Must be at least 8 characters",
placeholder: "Enter password",
required: true %>
<%= f.text_area :basic_bio,
label: "Bio",
caption: "Tell us about yourself",
rows: 4,
placeholder: "Write something..." %>
<%= f.submit "Create Account" %>
<% end %>
Input Sizes
Inputs come in three sizes: small, middle (default), and large.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :large_input,
label: "Large Input",
size: :large,
placeholder: "Large size" %>
<%= f.text_field :middle_input,
label: "Middle Input (Default)",
size: :middle,
placeholder: "Middle size" %>
<%= f.text_field :small_input,
label: "Small Input",
size: :small,
placeholder: "Small size" %>
<% end %>
Input Features
Inputs support prefixes, suffixes, icons, and clear buttons.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :amount,
label: "Prefix/Suffix Text",
prefix: "$",
suffix: "USD",
placeholder: "0.00" %>
<%= f.text_field :search,
label: "Prefix/Suffix Icons",
prefix_icon: :search,
suffix_icon: :info_circle,
placeholder: "Search..." %>
<%= f.text_field :clearable,
label: "Clear Button",
placeholder: "Type to see clear icon...",
allow_clear: true %>
<% end %>
Number Input
Numeric input with min, max, and step validation.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.number_field :age,
label: "Age",
min: 18,
max: 99,
step: 1,
placeholder: "18-99" %>
<%= f.number_field :quantity,
label: "Quantity",
min: 1,
max: 10,
value: 1 %>
<% end %>
TextArea Features
Multi-line text input with optional character count.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_area :description,
label: "Description",
rows: 4,
placeholder: "Enter your description here..." %>
<%= f.text_area :limited_text,
label: "With Character Count",
caption: "Maximum 200 characters",
rows: 4,
show_count: true,
maxlength: 200,
placeholder: "Type here..." %>
<% end %>
Password Features
Password input with visibility toggle.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.password_field :password_demo,
label: "Password",
caption: "Click the eye icon to toggle visibility",
prefix_icon: :lock,
placeholder: "Enter password" %>
<% end %>
Input Group
Input groups allow multiple inputs to be attached together.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= render Hakumi::Form::Item::Component.new(label: "Compact Group") do %>
<%= render Hakumi::Space::Compact::Component.new(block: true) do %>
<%= f.text_field :site, style: "width: 20%", value: "https://" %>
<%= f.text_field :domain, style: "width: 55%", value: "mysite" %>
<%= f.text_field :suffix, style: "width: 25%", value: ".com" %>
<% end %>
<% end %>
<% end %>
Form Buttons
Submit buttons with different types and sizes.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= render(Hakumi::Space::Component.new(size: :middle)) do %>
<%= f.submit "Primary", type: :primary %>
<%= f.submit "Default", type: :default %>
<%= f.submit "Large", type: :primary, size: :large %>
<%= f.submit "Small", type: :primary, size: :small %>
<% end %>
<% end %>
Inline Form
Inline forms are used to save vertical space.
Code
<%= hakumi_form_with(url: "/demo", layout: :inline, html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :inline_username, placeholder: "Username", prefix_icon: :user %>
<%= f.password_field :inline_password, placeholder: "Password", prefix_icon: :lock %>
<%= f.submit "Log in" %>
<% end %>
Disabled and Readonly
Inputs can be disabled or readonly.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :disabled_input,
label: "Disabled Input",
value: "This field is disabled",
disabled: true %>
<%= f.text_field :readonly_input,
label: "Readonly Input",
value: "This field is readonly",
readonly: true %>
<% end %>
Server-side Validation Errors
How server-side errors are displayed (simulated).
Code
<%
user = PlaygroundHelper::DemoUser.new(username: "taken_user", email: "invalid-email")
user.errors.add(:username, "Username is already taken")
user.errors.add(:email, "Invalid email format")
%>
<%= hakumi_form_with(model: user, url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :username,
label: "Username",
required: true %>
<%= f.text_field :email,
label: "Email",
required: true %>
<% end %>
Client-side Validation: Required
Basic required field validation with custom error message.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :req_username,
label: "Username",
placeholder: "Enter username",
rules: [{ required: true, message: "Username is required" }] %>
<%= f.submit "Submit" %>
<% end %>
Client-side Validation: Length
Validate minimum and maximum length.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :length_username,
label: "Username",
placeholder: "3-20 characters",
rules: [
{ required: true },
{ min_length: 3, message: "Minimum 3 characters" },
{ max_length: 20, message: "Maximum 20 characters" }
] %>
<%= f.submit "Submit" %>
<% end %>
Client-side Validation: Email
Built-in email validation.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :val_email,
label: "Email",
placeholder: "email@example.com",
rules: [
{ required: true, message: "Email is required" },
{ email: true, message: "Invalid email format" }
] %>
<%= f.submit "Submit" %>
<% end %>
Client-side Validation: Pattern
Validate using regular expressions.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :pattern_username,
label: "Username",
caption: "Only letters, numbers, and underscores allowed",
placeholder: "user_name123",
rules: [
{ required: true },
{ pattern: "^[a-zA-Z0-9_]+$", message: "Invalid characters" }
] %>
<%= f.submit "Submit" %>
<% end %>
Client-side Validation: Password Confirmation
Automatic validation when dependent fields change using validation rules.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.password_field :confirm_password,
label: "Password",
caption: "Enter a password",
placeholder: "Enter password",
rules: [{ required: true, message: "Password is required" }] %>
<%= f.password_field :confirm_password_confirmation,
label: "Confirm Password",
caption: "Will auto-validate when password changes",
placeholder: "Re-enter password",
rules: [
{ required: true, message: "Please confirm your password" },
{ match: "confirm_password", message: "Passwords do not match" }
] %>
<%= f.submit "Register" %>
<% end %>
Client-side Validation: Combined Rules
Multiple fields with different validation rules.
Code
<%= hakumi_form_with(url: "/demo", html: { style: "max-width: 600px;" }) do |f| %>
<%= f.text_field :combined_username,
label: "Username",
placeholder: "user_name123",
rules: [
{ required: true, message: "Required" },
{ min_length: 3, message: "Min 3 chars" },
{ max_length: 20, message: "Max 20 chars" },
{ pattern: "^[a-zA-Z0-9_]+$", message: "Letters, numbers, _ only" }
] %>
<%= f.text_field :combined_email,
label: "Email",
placeholder: "email@example.com",
rules: [
{ required: true },
{ email: true }
] %>
<%= f.submit "Submit" %>
<% end %>
Form Helper API (hakumi_form_with)
| Prop | Type | Default | Description |
|---|---|---|---|
model |
ActiveRecord or PORO |
- |
Object used for model-based forms. |
url |
String or Hash |
- |
URL for non-model forms. |
method |
:get | :post | :patch | :put or :delete |
:post |
HTTP verb passed to form_with. |
layout |
:horizontal | :vertical or :inline |
- |
Applies Hakumi form layout classes. |
builder |
Class |
Hakumi::FormBuilder |
Custom builder (defaults to Hakumi). |
html |
Hash |
- |
HTML attributes for the <form> tag (class merged with `hakumi-form`). |
block |
Proc |
required |
Yields the form builder instance. |
Form::Item API
| Prop | Type | Default | Description |
|---|---|---|---|
label |
String |
- |
Optional label rendered above the control. |
content slot |
Slot |
- |
Form control (input, select, etc.). |
**html_options |
Keyword args |
- |
Classes/data attributes merged into `.hakumi-form-item`. Pass as kwargs (e.g., `class:`, `style:`, `data:`). |