Miss the convenience of Rails when working in React? Tired of building React forms ever so slightly different from project to project? Prefer working with HTML over customizing the Rails form builder? Prefer HATEOAS? Boy, do I have the tool for you!
Introducing form_props, a new member of the React ❤️ Rails family, which includes
props_template, humid, and superglue. It’s a fork of Rails’s own
form_with
, made to output HTML attributes instead of HTML so you can wield the
power of Rails’s form in React, and even React Native!
How it works:
Within a jbuilder or props_template file: new.json.jbuilder
or new.json.props
json.create_form do
form_props(@post) do |f|
f.text :title
f.submit
end
end
Would output
{
"createForm": {
"props": {
"id": "create-post", "action": "/posts/123", "accept-charset": "UTF-8", "method": "post"
},
"extras": {
"method": { "name": "_method", "type": "hidden", "defaultValue": "patch", "autocomplete": "off"},
"utf8": { "name": "utf8", "type": "hidden", "defaultValue": "\u0026#x2713;", "autocomplete": "off"}
"csrf": {
"name": "utf8",
"type": "authenticity_token",
"defaultValue": "SomeTOken!23$",
"autocomplete": "off"
}
},
"inputs": {
"title": { "name": "post[title]", "id": "post_title", "type": "text", "defaultValue": "hello"},
"submit": {"type": "submit", "defaultValue": "Create Post"}
}
}
}
then build a form component
import React from 'react'
export default ({props, inputs, extras}) => {
<form {...props}>
{Object.values(extras).map((hiddenProps) => (<input {...hiddenProps} type="hidden"/>))}
// Bring your own components
<input {...inputs.title} type="text"aria-label="Your Title"/>
// or let the designer nest the input in the label. No form builder knowledge needed!
<label for={inputs.title.id}>Your Title</label>
<input {...inputs.submit} type="submit"/>
</form>
}
and use the payload. If you’re using Superglue, this is passed to your page component:
export const newPostPage = (newPageProps)=> {
const {header, createForm} = newPageProps;
return (
<>
<h1>{header}</h1>
<CreatePostForm {...createForm} />
</>
)
}
Otherwise, you’ll need to add it to your API, for example:
const [newPageProps, setNewPageProps] = useState(null);
useEffect(() => {
const fetchData = async () => {
const rsp = await fetch(`/api/posts/new`);
setNewPageProps(rsp)
};
});
Some helpers like f.select
, and f.collection_checkboxes
require you to build
custom components.
Head over to the documentation for more information!