# Autocomponents  Gadget provides high-level, super-automatic components for assembling working user interfaces very quickly called _autocomponents_. Autocomponents are React components that implement forms and tables that can read and write to Gadget data in your app's database. Autocomponents are available in different design systems and can be made to look and feel like the rest of your app. ## When to use autocomponents  Autocomponents are intended to be high-quality interfaces for common tasks. While autocomponents offer a remarkably high degree of customizability, they are designed to help you build fast rather than build perfect. They are not intended to be a replacement for fully custom or artisanally designed user interfaces. If you need fine-grained control over your UX, Gadget recommends using the [headless hooks](https://docs.gadget.dev/reference/react#useactionform) that power autocomponents with head-ful design elements on top! ## Installing autocomponents  Because autocomponents use a design system, you need to install the design system's dependencies to use them. Currently, Gadget supports the following design systems: * [Shopify Polaris](https://polaris.shopify.com/) * [Shadcn](https://ui.shadcn.com/) Autocomponents are only available in `@gadgetinc/react` version 0.16.0 and later. To upgrade to the latest version, run the following in the Gadget command palette: ```bash yarn add @gadgetinc/react ``` ## ``  `` renders a form that calls one of your app's backend API actions. On form submit, `` can call one of your [model actions](https://docs.gadget.dev/guides/actions/types-of-actions#model-actions) such as create, update, or a custom action. [Global actions](https://docs.gadget.dev/guides/actions/types-of-actions#global-actions) can also be run by ``. `` renders the correct HTML input element for each backend field and includes support for form validation, relationship fields, error handling, autocomplete, and file uploads. For example, if you have a backend `widget` model with a `name` and `inventoryCount` field, you can render a form to create a new widget like so: ```tsx import { api } from "../api"; export default function Example() { return ; } ``` `AutoForm` components can also be given an explicit set of children which lets you re-order, wrap, and replace child fields as needed: ```tsx import { api } from "../api"; export default function Example() { return (
{/** put these two auto inputs in a wrapper component to align them horizontally */}
{/** render a submit button */}
); } ``` Using `` without specifying the or explicitly passing children will render a form with all fields from the model or all params for an action. This means that adding a new field to a model or params to a global action will also add an input for that field to the form. Make sure you test any default `` components after making changes to your models or actions to ensure they still work as expected. ### Choosing fields for the form  By default, `` will render input components to set or edit data for each field on a model record, or each global action parameter. Form inputs can be removed, re-ordered, or grouped. To include only some of the fields of a model or action in your form, pass the `include` option with a list of fields to render: ```tsx ``` `include` can also be used to quickly re-order the list of fields, as fields will be rendered in the order specified in the `include` list: ```tsx ``` To exclude some fields from your model and render all the others, pass the `exclude` options with a list of fields to omit from the form: ```tsx ``` You cannot have `include` and `exclude` defined for the same form. `` does not currently support custom `params` with the `object` or `array` types. ### AutoForm rich text fields  The auto-generated input for rich text fields in AutoForms require an extra dependency to be installed: ```bash // in install the rich text editor dependency yarn add -D @mdxeditor/editor ``` Then import the stylesheet into your app: ```tsx import "@mdxeditor/editor/style.css"; ``` ### Custom form components  `` can be passed an explicit set of children components or HTML elements to render instead of the default auto-generated components. This allows full control of field order and layout, and provides the ability to mix and match autocomponents with custom inputs. To begin customizing the children, open the `` tag and pass the children components or HTML elements you'd like to render, like so: ```tsx

My form title

{/* more form elements*/}
``` To keep your form looking like the fully-automatic version of an ``, replace each field with an `` element and add an `` element: ```tsx ``` #### Custom form title  `` has a `title` prop that can be used to override the default form title. This is useful when you want a custom form title but want to use the auto-generated input components for a form: ```tsx ``` The title can also be hidden by passing `title={false}`: ```tsx ``` #### Inputs with ``  `` renders an automatic input for the provided field, selecting the right kind of control, formatting, and experience for inputting data for a given field type. ``'s automatic input selection uses `` under the hood, so if you want to take over and customize the layout of your form while using the same input components, you can keep using a fully automatic version of each field with ``. For example, you can convert the form from the previous section to use explicit children like so: ```tsx // before () => ; // after () => ( ); ``` The `field` prop for each `` specifies the model field to accept input for. You can also add HTML elements or layout components to augment the form layout: ```tsx () => (
); ``` #### Customizing ``  If you would like to have more control over the input's appearance, you can use the individual input types directly: ```tsx // before () => ( ); // after () => ( {/* Field specific input components can take in additional props that are not available in the general AutoInput component */} ); ``` To see a full list of input components available, see the [autocomponent reference](https://docs.gadget.dev/reference/react/auto). ### Call `update` on submit and fetch existing records  `Autoform` can also be used for `update` actions. An existing record can be automatically fetched by passing the record `id` into the `findBy` prop. You need to make sure your current user role has read access to the model you are trying to fetch. ```tsx ``` To fetch an existing record by something other than `id`, pass the `findBy` prop a set of conditions to find by: ```tsx ``` When using a findBy for a field other than id, it requires a by-field record finder like `.findBySlug` to exist for your model, which is generated by adding a [uniqueness validation](https://docs.gadget.dev/guides/models/fields#uniqueness-validation) to a field. ### Call `custom` model actions on submit  `` can also be used to call `custom` model actions. Appropriate input components will be rendered for any [custom `params` defined](https://docs.gadget.dev/guides/actions/code#accepting-more-parameters) for the action. These `custom` actions require a record to be passed in, so you must pass the `findBy` prop to fetch the record to run the action on. ```tsx ``` For example, if you have a custom `widget.reconfigure` action that has `state: string` and `value: number` params defined, the default `` will render with a text input for `name` and a number input for `value`. To fetch an existing record by something other than `id`, pass the `findBy` prop a set of conditions to find by: ```tsx ``` ### Call a global action on submit  `` can also be used to call [global actions](https://docs.gadget.dev/guides/actions/types-of-actions#global-actions). Appropriate input components will be rendered for any [custom `params` defined](https://docs.gadget.dev/guides/actions/code#accepting-more-parameters) for the action. ```tsx ``` ### Setting initial values for create forms  Forms for `create` actions will automatically populate with default values set for fields in your backend Gadget models. For example, if you have set the default `inventoryCount` for the `widget` model to 0 in the model schema page, the form will start with the `inventoryCount` field set to 0. If you'd like to pre-populate the form with specific values when creating new records, you can also pass the `defaultValues` prop to set explicit initial values for the form: ```tsx ``` `defaultValues` must be passed in the **fully-qualified** form that includes the model name, like `widget.name`, instead of just `name`. This wrapper object allows the form to store other state beyond just the model data, and matches your app's API format under the hood. ```tsx ``` Don't do this: ```tsx ``` ### Hidden inputs  You can submit hardcoded hidden values along with the form for values you do not want the user to edit. ```tsx () => ( ); ``` ### Form validation  Validation is automatically applied to all `` inputs. The default validation rules are set using the field validation rules set on a model's schema. #### Validating custom params  For custom parameters on model or global actions, you can manually validate `params` passed into the action from an ``. If a value is invalid, you can return an `InvalidRecordError` with a message to display to the user. This validation is done in your actions, not in the frontend. Here's a sample action that validates a custom `params` object: ```typescript // import InvalidRecordError from gadget-server import { InvalidRecordError } from "gadget-server"; export const run: ActionRun = async ({ params, logger, api, connections }) => { // validate the param manually if (params.count < 0 || params.count > 100) { throw new InvalidRecordError("count param not valid", [ { apiIdentifier: "customUpload", message: "count must be between 0 and 100" }, ]); } // ... custom action code }; export const params = { count: { type: "number" }, }; ``` You can call this action from an `` and the validation error will be displayed: ```tsx ``` To learn about setting validations on fields, see the [field validation](https://docs.gadget.dev/guides/models/fields#extending-fields-with-validations) guide. `` does not support custom client-side validation. ### Manual form control using `react-hook-form`  If you need to manually control the form state, you can use the `react-hook-form` hooks directly. This is useful if you need to integrate with form state that is not provided by ``, or if you need to manually control the form state for some other reason. For example, to clear the values inside an input, the `useFormContext` hook from `react-hook-form` to access the `setValue` function and set the value of the name field to an empty string: ```tsx import { api } from "../api"; // import useFormContext to get access to react-hook-form API import { useFormContext } from "react-hook-form"; export default function () { return (
); } // custom component that selects a product using an external resource picker const ClearButton = () => { // use setValue to manually manage form state for the selected product const { setValue } = useFormContext(); return ( ); }; ``` ### Running code after form submission  The `` also has an `onSuccess` callback hook that allows you to run code after the form has been successfully submitted. This can be useful for things like redirecting the user to a new page, showing a success message, or updating the UI in some way. ```tsx () => ( { console.log("created record:", record.inventoryCount); }} /> ); ``` ## ``  `` renders a button that when clicked calls one of your app's backend API actions with variables passed as a prop. You can use `` for [model actions](https://docs.gadget.dev/guides/actions/types-of-actions#model-actions) to create, update, or delete records, or to call a [global action](https://docs.gadget.dev/guides/actions/types-of-actions#global-actions). `` renders a button from the design system you're using, so it fits right in with the rest of your application and doesn't require any additional styling. To render an ``, pass the `action` prop with the backend API action you want to call. ```tsx // when clicked, will run api.widget.create() ``` When clicked, this button will run the action, and show a success or error toast when it completes. It will also show a nice loading spinner while the action is running. Often, you'll need to pass `variables` to your action. Pass them in the same style as you would pass them to your app's JS client: ```tsx // when clicked, will run api.widget.create({ name: "foobar", inventoryCount: 0 }) ``` Variables can be set dynamically using the normal React state management tools, like a `useState` hook: ```tsx const CreateWidgetButton = () => { const [variables, setVariables] = useState({ name: "foobar", inventoryCount: 0 }); return ; }; ``` ### Button labels and styling  `` accepts all the props from the design system you're using, so you can control its look and feel in the same way you would control the `