Contact Form: Add Gutenberg based form builder blocks#9452
Contact Form: Add Gutenberg based form builder blocks#9452lsl wants to merge 2 commits intoAutomattic:masterfrom lsl:try/gutenberg-contact-form
Conversation
At this point it just represents the parent form -- it doesn't handle any fields yet. That will largely depend on how WordPress/gutenberg#3745 progresses.
Adds a set of Gutenberg "Form" blocks for use with the contact form module. Blocks: * Form - The main block, consists of an InnerBlock for the <form> element and a set template consisting of a default set of inner blocks preconfigured as a contact form * Text - General <input type=text>/<textarea> field with configurable label, rows * Button - A <button type=submit> with configurable button text Blocking Release: * InnerBlock templating requires WordPress/gutenberg#5452. * WordPress/gutenberg#5452 needs to override isPrivate settings to prevent form blocks being seen in the inserter when out of form context. * WordPress/gutenberg#5452 is whitelist only meaning we cant add extra blocks in between form elements - not really a huge issue for this but likely an issue for other use cases. Todo - Integration with grunion-contact-form: * Captcha support should be relatively easy to achieve with a serverside rendered block * A server side filter / hook could replace the form action Todo - Handle duplicate field names gracefully * Currently uses a variation on the label / field name to set id / for settings on label / inputs. * Currently uses same variation for <input name=""> attributes
noisysocks
left a comment
There was a problem hiding this comment.
Overall, I really like the approach you're taking here by using InnerBlocks. Nice work.
I left a few mostly minor comments. Note that many of them (e.g. missing key props, missing localisation) apply to all four JSX files added in this PR.
I'd like to see the contact form functionality itself implemented, e.g. one should be able to send an email by submitting the form on the frontend. Once that works we'll be in a good position to refine this PR into something shippable.
| const inputName = (str) => str.toLowerCase().replace(/[^a-z0-9]/, ''); | ||
|
|
||
| // Define the form block | ||
| let FormButton = { |
There was a problem hiding this comment.
We should communicate that we don't intend for this variable's value to change by declaring it const.
|
|
||
| save: ( { attributes, className } ) => { | ||
| return <div className={ className }> | ||
| <Button isPrimary={ true } type={ "submit" }> |
There was a problem hiding this comment.
We can shorten this to:
<Button isPrimary type="submit">https://reactjs.org/docs/jsx-in-depth.html#string-literals
https://reactjs.org/docs/jsx-in-depth.html#props-default-to-true
| } | ||
|
|
||
| return [ | ||
| <TextControl |
There was a problem hiding this comment.
We'll need to specify a key prop on the <TextControl> since it is contained within a list.
Better yet, we could just omit the list altogether:
return (
<TextControl
...
/>
);| }, | ||
| edit: ( { attributes, setAttributes, className, isSelected } ) => { | ||
| if ( ! isSelected ) { | ||
| return <div className={ className }> |
There was a problem hiding this comment.
JSX is easier to read, I think, when opening and closing tags align. We can do this by wrapping multiline JSX with parentheses.
if ( ! isSelected ) {
return (
<div className={ className }>
...
</div>
);
}| @@ -0,0 +1 @@ | |||
| .wp-block-jetpack-form-button {} | |||
There was a problem hiding this comment.
No, development artifacts to remove.
| />, | ||
|
|
||
| // Display on Focus | ||
| !! isSelected && |
There was a problem hiding this comment.
We can remove this check. WordPress/gutenberg#5029 made <InspectorControls> check for isSelected automatically.
| // The id needs to be unique for for="" but also needs to be saved for block validation | ||
| const id = 'jetpack-form-text-input-' + inputName( attributes.label ); | ||
|
|
||
| return <BaseControl label={ attributes.label } id={ id }> |
There was a problem hiding this comment.
I don't think using <BaseControl> in save() is a good idea. If, down the track, we modify the markup within BaseControl, Gutenberg will be unable to parse existing jetpack/form-text blocks.
I recommend instead that we manually render the necessary <label> markup here.
|
|
||
| edit: ( { attributes, setAttributes, className, isSelected } ) => { | ||
| if ( ! isSelected ) { | ||
| return FormText.save( { attributes: attributes, className: className } ) |
There was a problem hiding this comment.
Clever! I think it would be clearer, though, if we split this out into its own component that both save() and edit() use.
function FormTextInput( { attributes, className } ) {
return ...;
}
const FormText = {
save( { attributes, className } ) {
return <FormTextInput attributes={ attributes } className={ className } />;
},
edit( { attributes, setAttributes, className, isSelected } ) {
if ( ! isSelected ) {
return <FormTextInput attributes={ attributes } className={ className } />;
}
},
...
};| } | ||
|
|
||
| return [ | ||
| <TextControl |
There was a problem hiding this comment.
This is missing a key prop. Alternatively, we could use Fragment (exposed as wp.element.Fragment) instead of a list.
|
|
||
| if ( "form" == $name ) { | ||
| $namespace = "jetpack/form"; | ||
| } |
There was a problem hiding this comment.
There's some mixed indentation going on here.
|
I think this needs a rebase before I can test it. There was a bug introduced to Jetpack that bricks the admin screen for me. |
| JETPACK__VERSION | ||
| ); | ||
|
|
||
| register_block_type( $type, array( |
|
To check this PR (which comes from a fork of the Jetpack repo) when working on a local clone of the Automattic/Jetpack repo: Make sure Gutenberg is installed and Jetpack is connected. |
|
@lsl could you create a version of this branch but on this same repo instead of being a branch on a fork ? |
Context: #9452 @oskosk Requested this unfinished branch to be pushed up to Automattic/jetpack for use in the Jetpck Beta Tester Plugin. -- Adds a set of Gutenberg "Form" blocks for use with the contact form module. Blocks: * Form - The main block, consists of an InnerBlock for the <form> element and a set template consisting of a default set of inner blocks preconfigured as a contact form * Text - General <input type=text>/<textarea> field with configurable label, rows * Button - A <button type=submit> with configurable button text Blocking Release: * Fix issues identified in original PR #9452 * InnerBlock templating requires WordPress/gutenberg#5452. * WordPress/gutenberg#5452 needs to override isPrivate settings to prevent form blocks being seen in the inserter when out of form context. * WordPress/gutenberg#5452 is whitelist only meaning we cant add extra blocks in between form elements - not really a huge issue for this but likely an issue for other use cases. Todo - Integration with grunion-contact-form: * Captcha support should be relatively easy to achieve with a serverside rendered block * A server side filter / hook could replace the form action Todo - Handle duplicate field names gracefully * Currently uses a variation on the label / field name to set id / for settings on label / inputs. * Currently uses same variation for <input name=""> attributes
|
Thank you @lsl ! |

Status: In Progress
Adding a Gutenberg form builder to Jetpack for use in the contact form module.
There are a couple of issues blocking any kind of usable solution being completed, outlined further below.
Changes proposed in this Pull Request:
Testing instructions:
Proposed changelog entry for your changes:
Further info:
Blocks:
<form>element and a set template consisting of a default set of inner blocks
preconfigured as a contact form
<input type=text>/<textarea>field with configurablelabel, rows
<button type=submit>with configurable button textBlocking Release:
Todo - Integration with grunion-contact-form:
rendered block
Todo - Handle duplicate field names gracefully:
id / for settings on label / inputs.
<input name="">attributesHow it looks:
