Our Form component provides great user experience to collect some data from a user and submit it for extensions needs.
Two Types of Items: Controlled vs. Uncontrolled
Items in React can be one of two types: controlled or uncontrolled.
An uncontrolled item is the simpler of the two. It's the closest to a plain HTML input. React puts it on the page, and Raycast keeps track of the rest. Uncontrolled inputs require less code, but make it harder to do certain things.
With a controlled item, YOU explicitly control the value that the item displays. You have to write code to respond to changes with defining onChange callback, store the current value somewhere, and pass that value back to the item to be displayed. It's a feedback loop with your code in the middle. It's more manual work to wire these up, but they offer the most control.
You can take look at these two styles below under each of the supported items.
Validation
Before submitting data, it is important to ensure all required form controls are filled out, in the correct format.
In Raycast, validation can be fully controlled from the API. To keep the same behavior as we have natively, the proper way of usage is to validate a value in the onBlur callback, update the error of the item and keep track of updates with the onChange callback to drop the error value. The useForm utils hook nicely wraps this behaviour and is the recommended way to do deal with validations.
Keep in mind that if the Form has any errors, the Action.SubmitFormonSubmit callback won't be triggered.
import { Form } from"@raycast/api";import { useState } from"react";exportdefaultfunctionCommand() {const [nameError,setNameError] =useState<string|undefined>();const [passwordError,setPasswordError] =useState<string|undefined>();functiondropNameErrorIfNeeded() {if (nameError &&nameError.length>0) {setNameError(undefined); } }functiondropPasswordErrorIfNeeded() {if (passwordError &&passwordError.length>0) {setPasswordError(undefined); } }return ( <Form><Form.TextField id="nameField" title="Full Name" placeholder="Tim Cook" error={nameError} onChange={dropNameErrorIfNeeded} onBlur={(event) => {if (event.target.value?.length==0) {setNameError("The field should't be empty!"); } else {dropNameErrorIfNeeded(); } }}/><Form.PasswordField id="password" title="New Password" error={passwordError} onChange={dropPasswordErrorIfNeeded} onBlur={(event) => {constvalue=event.target.value;if (value &&value.length>0) {if (!validatePassword(value)) {setPasswordError("Password should be at least 8 characters!"); } else {dropPasswordErrorIfNeeded(); } } else {setPasswordError("The field should't be empty!"); } }}/><Form.TextArea id="bioTextArea" title="Add Bio" placeholder="Describe who you are"/><Form.DatePicker id="birthDate" title="Date of Birth"/></Form> );}functionvalidatePassword(value:string):boolean {returnvalue.length>=8;}
Drafts
Drafts are a mechanism to preserve filled-in inputs (but not yet submitted) when an end-user exits the command. To enable this mechanism, set the enableDrafts prop on your Form and populate the initial values of the Form with the top-level prop draftValues.
Drafts for forms nested in navigation are not supported yet. In this case, you will see a warning about it.
A form item with a text area for input. The item supports multiline text entry.
Example
import { ActionPanel, Form, Action } from"@raycast/api";constDESCRIPTION= "We spend too much time staring at loading indicators. The Raycast team is dedicated to make everybody interact faster with their computers.";
export default functionCommand() {return (<Form actions={ <ActionPanel> <Action.SubmitForm title="Submit Description" onSubmit={(values) => console.log(values)} /> </ActionPanel> }><Form.TextArea id="description" defaultValue={DESCRIPTION} /></Form> );}
A method that determines if a given date represents a full day or a specific time.
import { ActionPanel, Form, Action } from"@raycast/api";exportdefaultfunctionCommand() {return (<Form actions={ <ActionPanel> <Action.SubmitForm title="Create Event" onSubmit={(values) => {if (Form.DatePicker.isFullDay(values.reminderDate)) {// the event is for a full day } else {// the event is at a specific time } }} /> </ActionPanel> }><Form.DatePicker id="eventTitle" title="Title"/><Form.DatePicker id="eventDate" title="Date"/></Form> );}
A form item with a button to open a dialog to pick some files and/or some directories (depending on its props).
While the user picked some items that existed, it might be possible for them to be deleted or changed when the onSubmit callback is called. Hence you should always make sure that the items exist before acting on them!
The types of date components the user can pick with a Form.DatePicker.
Enumeration members
Imperative API
You can use React's useRef hook to create variables which have access to imperative APIs (such as .focus() or .reset()) exposed by the native form items.