VTEX Developer Portal

All ContributorsAll Contributors

The Store Form app provides blocks responsible for displaying an user form connected to Master Data through a JSON schema.

imageimage

Configuration

:warning: Before configuring the Store Form block in your theme, make sure you've already configure a JSON schema in Master Data, otherwise the client form won't be properly saved. To more info, access the recipe on Creating forms for your store users.

  1. Add store-form app to your theme's dependencies in the manifest.json, for example:
dependencies: {
  "vtex.store-form": "0.x"
}

Now, you are able to use all blocks exported by the store-form app. Check out the full list below:

Block nameDescription
formhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red Top level block in which you will specify which entity and schema from Master Data will be used for building the form. It provides context to all its 8 children blocks (listed below).
form-input.checkboxRenders a checkbox field in the form.
form-input.dropdownRenders a dropdown field in the form.
form-input.radiogroupRenders a radio buttons field in the form.
form-input.textareaRenders a big text field in the form.
form-input.textRenders a small text field in the form which has few available characters.
form-field-groupRenders different form blocks (such as form-input.radiogroup and form-input.text) according to each schema's sub-properties type.
form-input.uploadRenders an Upload field in the form.
form-submitRenders a button to submit the user form content.
form-successAccepts an array of blocks that will be rendered when the form is successfully submitted. Any children block is valid.
  1. In any desired store template, such as the store.product, add the form block.
    In the example below, the form block is contained in a Flex Layout row:
{
 "store.product": {
   "children": [
     "flex-layout.row#product-breadcrumb",
     "flex-layout.row#product-main"
+    "flex-layout.row#form",
     "shelf.relatedProducts",
     "product-reviews",
     "product-questions-and-answers"
   ]
 },
  1. Then, declare the form block. Bear in mind to specify which entity and schema from Master Data should be fetched to build the block.
{
  "flex-layout.row#form": {
    "children": [
      "flex-layout.col#form"
    ]
  },
  "flex-layout.col#form": {
    "children": [
      "form"
    ]
  },
  "form": {
    "props": {
      "entity": "clients",
      "schema": "person"
    }
  }
}

:information_source: If the form block does not have any children configured, a default form will be rendered automatically based on the JSON schema in Master Data. This reading and interpretation of JSON schemas is due to the Reacht Hook Form JSON Schema library (which is supporting the Store Form blocks logic behind the scenes).

Prop nameTypeDescriptionDefault Value
entitystringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red The entity in Master Data where the document will be saved.undefined
schemastringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red The JSON schema name that will be used. The schema name is set in the API's request to create it in Master Data.undefined
  1. If desired, complete the form block by adding and configuring an array of children blocks. You can use the blocks listed in the first table stated above. For example:
  "form": {
    "props": {
      "entity": "clients",
      "schema": "person"
    },
    "children": [
      "rich-text#formTitle",
      "form-input.text#firstName",
      "form-input.text#lastName",
      "form-field-group#address",
      "form-input.checkbox#agreement",
      "form-submit"
    ],
    "blocks": ["form-success"]
  },
  "form-success": {
    "children": [
      "rich-text#successSubmit"
    ]
  },
  "rich-text#successSubmit": {
    "props": {
      "text": "Succesfully submitted the data!",
      "textAlignment": "CENTER",
      "textPosition": "CENTER"
    }
  },
  "form-input.text#firstName": {
    "props": {
      "pointer": "#/properties/firstName"
    }
  },
  "form-input.text#lastName": {
    "props": {
      "pointer": "#/properties/lastName"
    }
  },
  "form-input.checkbox#agreement": {
    "props": {
      "pointer": "#/properties/agreement",
      "label": "Do you agree that this is the best form component in the whole wide world?"
    }
  },
  "form-field-group#address": {
    "props": {
      "pointer": "#/properties/address"
    }
  },
  "form-submit": {
    "props": {
      "label": "Submit"
    }
  }

form-input.radiogroup, form-input.dropdown, form-input.textarea and form-input.checkbox props

Prop nameTypeDescriptionDefault Value
pointerstringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red JSON schema pointer i.e. the JSON schema path (for example: #/properties/firstName) in which the form block inputs should be validated against.undefined
labelstringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red Field's name when renderedProperty's title

form-input.textarea props

Prop nameTypeDescriptionDefault Value
placeholderstringPlaceholder for the textarea input.undefined

form-input.text props

Prop nameTypeDescriptionDefault Value
pointerstringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red JSON schema pointer i.e. the JSON schema path (for example: #/properties/firstName) in which the form block inputs should be validated against.undefined
inputTypeenumDefines which type of a text field should be rendered:
input: renders a normal text field.
hidden: does not render any text field. It should be used in scenarios in which you want to pre-define a field value to be submitted to the form but that shouldn't be visible (and therefore editable) to users.
password: renders a password text field.
input
labelstringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red Field's name when renderedProperty's title
placeholderstringPlaceholder for the text input.undefined

form-field-group props

Prop nameTypeDescriptionDefault Value
pointerstringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red JSON schema pointer i.e. the JSON schema path (for example: #/properties/address) in which the form block inputs should be validated against. Note that since you are configuring a form-field-group block, the path must not include a schema's sub-property, only a schema's property.undefined
uiSchemaobjectRedefines how the form-field-groups block should render each sub-properties declared in the JSON schema path defined in pointer. As said previously, the form-field-groups already does that by itself, but you can overwrite the sub-properties types through a schema and so redefine how each form block will be rendered.undefined

form-input.upload props

Prop nameTypeDescriptionDefault Value
pointerstringhttps://img.shields.io/badge/-Mandatory-redhttps://img.shields.io/badge/-Mandatory-red JSON schema pointer i.e. the JSON schema path (for example: #/properties/address) in which the form block inputs should be validated against. Note that since you are configuring a form-field-group block, the path must not include a schema's sub-property, only a schema's property.undefined
acceptstringhttps://img.shields.io/badge/-optional-yellowhttps://img.shields.io/badge/-optional-yellow By default the upload input just accept image and PDF format files. If you want to customize it, you can pass the format type that you want following this pattern: *.TYPEFILE. You can read more about the accept field.
  • uiSchema object:
const UISchema = {
  type: UIType,
  properties: {
    // Note that the definition is recursive
    childName: {UISchema},
    childName: {UISchema},
    // ...
    childName: {UISchema},
  },
}

Where childName should be replaced for the desired sub-property name and the UIType should be replaced for one of the following values:

  • default: will consider the form-field-group own logic (e.g. using the React Hook Form JSON Schema library) for block's rendering;
  • radio: the sub-property will be rendered as a form-input.radiogroup block.
  • select: the sub-property will be rendered as a form-input.dropdown block.
  • input: the sub-property will be rendered as a form-input.text block with inputType set to input.
  • hidden: the sub-property will be rendered as a form-input.text block with inputType set to hidden.
  • password: the sub-property will be rendered as a form-input.text block with inputType set to password.
  • textArea: the sub-property will be rendered as a form-input.textarea block.
  • checkbox: the sub-property will be rendered as aform-input.checkbox block.
  • upload: the sub-property will be rendered as aform-input.upload block.

Modus operandi

The JSON schema created in Master Data is firstly responsible for telling form blocks which data they must receive i.e. specifying which kind of input each form field should expect from users.

When the user clicks on the Submit button, the form blocks then fetch all input data and send it to the Schema validation. This process of understanding which input they must receive and sending it to Master Data is done by using the React Hook Form JSON schema library behind the scenes.

If any unexpected answer is detected, that is, if the form blocks data does not match the Schema, Master Data won't be able to create an user form and an error message will be returned for the user.

Customization

In order to apply CSS customizations in this and other blocks, follow the instructions given in the recipe on Using CSS Handles for store customization.

CSS Handles
form
formLoading
formErrorLoading
formSubmitContainer
formSubmitButton
formErrorServer
formErrorUserInput

Contributors ✨

Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind are welcome!

Updated 3 months ago


Store Form


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.