Closed jho406 closed 1 year ago
@jho406 here's where I left off:
require "active_support/core_ext/string"
require "rspec"
# TODO: form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
def form_props(url: nil, scope: nil, **options)
builder = MyFormBuilder.new(url: url, scope: scope, **options)
yield builder
builder.to_h
end
class MyFormBuilder
attr_reader :scope
def initialize(url: nil, scope: nil, **options)
@scope = scope
@output = {
accept_charset: "UTF-8",
action: url || "/",
method: options [:method] || "post",
elements: {}
}
end
def text_field(method, options = {})
@output[:elements][scope ? "#{scope}_#{method}".to_sym : method.to_s.to_sym] = {
type: "text",
label: method.to_s.humanize,
name: scope ? "#{scope}[#{method}]" : method.to_s
}.merge(options)
end
def email_field(method, options = {})
@output[:elements][scope ? "#{scope}_#{method}".to_sym : method.to_s.to_sym] = {
type: "email",
label: method.to_s.humanize,
name: scope ? "#{scope}[#{method}]" : method.to_s
}.merge(options)
end
def to_h
@output
end
end
RSpec.describe "form props" do
it "builds default attributes for the form" do
props = form_props {}
expect(props).to eq(
accept_charset: "UTF-8",
action: "/",
method: "post",
elements: {}
)
end
it "sets attributes for the form" do
props = form_props(url: "/some_url", method: "get") {}
expect(props).to eq(
accept_charset: "UTF-8",
action: "/some_url",
method: "get",
elements: {}
)
end
it "builds attributes for the form elements" do
props = form_props do |my_form_builder|
my_form_builder.text_field :first_name, min: 50
my_form_builder.email_field :email, required: true, label: "Email address"
end
expect(props[:elements]).to eq(
first_name: {
type: "text",
min: 50,
label: "First name",
name: "first_name"
},
email: {
type: "email",
required: true,
label: "Email address",
name: "email"
}
)
end
it "scopes form elements" do
props = form_props(scope: "user") do |my_form_builder|
my_form_builder.text_field :first_name
my_form_builder.email_field :email
end
expect(props[:elements]).to eq(
user_first_name: {
type: "text",
label: "First name",
name: "user[first_name]"
},
user_email: {
type: "email",
label: "Email",
name: "user[email]"
}
)
end
end
Closing this as https://github.com/thoughtbot/form_props has been created! 🥳
Rail's form helpers are an incredible way to quickly build forms from backend objects. I'd like to have some parity on the superglue side so quickly build uncontrolled components on the React side without using
RailsTag
Something like this:
then on the Javascript side:
We leave how to structure the form up to the user so they can do this if they want in only html: