-
Notifications
You must be signed in to change notification settings - Fork 1
713 examples - move readmes to docusaurus #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
erika-howell
wants to merge
2
commits into
main
Choose a base branch
from
713-examples--move-readmes-to-docusaurus
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
...developer-documentation/examples-and-templates/examples/computed-form-fields.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| --- | ||
| description: Automatically calculates a read-only field in forms | ||
| title: Computed Form Fields | ||
| id: computed-form-fields | ||
| --- | ||
|
|
||
| # Computed Form Fields Example | ||
|
|
||
| This example shows you how to build a form with computed form fields. Computed form fields automatically calculate a value based on a separate read-only field. For example, if a user inputs a quantity, a computed form field can multiply that number by a price to give a total cost. | ||
|
|
||
| Learn more about RADFish examples at the official [documentation](https://nmfs-radfish.github.io/radfish/developer-documentation/examples-and-templates#examples). Refer to the [RADFish GitHub repo](https://nmfs-radfish.github.io/radfish/) for more information and code samples. | ||
|
|
||
| ## Preview | ||
| This example will render as shown in this screenshot: | ||
|
|
||
|  | ||
|
|
||
| ## Steps | ||
|
|
||
| ### 1. Define Constants for Input Fields | ||
|
|
||
| Before building out your form, define constants for each input field. Using constants helps reduce errors and makes your logic more maintainable. | ||
|
|
||
| ```jsx | ||
| const SPECIES = "species"; | ||
| const NUMBER_OF_FISH = "numberOfFish"; | ||
| const COMPUTED_PRICE = "computedPrice"; | ||
| ``` | ||
|
|
||
| In this example, we will build a form with three inputs. The values from the first two inputs will compute the value of `computedPrice`. | ||
|
|
||
| ### 2. Initialize the Form Component with State | ||
|
|
||
| Next, we'll define the main form component. To manage the data entered in the form, we initialize it with a `formData` state variable, which is an empty object. This state will dynamically store the values of the form fields as users interact with the form. | ||
|
|
||
| The `setFormData` function allows us to update the state whenever an input changes. This ensures the form data is kept in sync. | ||
|
|
||
| ```jsx | ||
| const ComputedForm = () => { | ||
| const [formData, setFormData] = useState({}); | ||
|
|
||
| return ( | ||
| // form JSX will go here | ||
| ); | ||
| }; | ||
| ``` | ||
|
|
||
| ### 3. Structuring the Form with Inputs | ||
|
|
||
| In the `return` statement of the component, use the Trussworks `Form` component to structure your form. Within the form, include input components such as `TextInput`, referencing the variables defined in Step 1 (e.g. `NUMBER_OF_FISH`) instead of hardcoding strings. This practice helps avoid typos and ensures consistency when accessing the `formData` state. For better organization and styling, wrap your inputs within the `FormGroup` component provided by Trussworks. | ||
|
|
||
| ```jsx | ||
| return ( | ||
| <Form | ||
| onSubmit={handleSubmit} | ||
| className="maxw-full margin-205 padding-205 bg-white radius-8px shadow-2" | ||
| > | ||
| <FormGroup> | ||
| <Label className="text-bold" htmlFor={NUMBER_OF_FISH}> | ||
| Number of Fish | ||
| </Label> | ||
| <TextInput | ||
| className="text-bold" | ||
| id={NUMBER_OF_FISH} | ||
| name={NUMBER_OF_FISH} | ||
| type="number" | ||
| placeholder="0" | ||
| value={formData[NUMBER_OF_FISH] || ""} | ||
| /> | ||
| ``` | ||
|
|
||
| ### 4. Adding Input Handlers for Form Fields | ||
|
|
||
| Use `handleNumberFishChange` and `handleSelectChange` to manage the state for the **Number of Fish** and **Species** fields. These functions update the `formData` state whenever the user interacts with the inputs. | ||
|
|
||
| For the **Number of Fish** input, the `handleNumberFishChange` function captures the input value and updates the corresponding field in the `formData` state. Similarly, the `handleSelectChange` function updates the state when the user selects a species. | ||
|
|
||
| This function handles changes in the **Number of Fish** input field: | ||
| ```jsx | ||
| const handleNumberFishChange = (event, formData) => { | ||
| const { value } = event.target; | ||
| setFormData({ | ||
| ...formData, // Preserve existing form data | ||
| [NUMBER_OF_FISH]: value, // Update the "Number of Fish" field | ||
| }); | ||
| }; | ||
| ``` | ||
|
|
||
| Use the `handleNumberFishChange` function to manage the **Number of Fish** input: | ||
| ```jsx | ||
| <TextInput | ||
| className="text-bold" | ||
| id={NUMBER_OF_FISH} | ||
| name={NUMBER_OF_FISH} | ||
| type="number" | ||
| placeholder="0" | ||
| value={formData[NUMBER_OF_FISH] || ""} // Display the current state value | ||
| onChange={(event) => handleNumberFishChange(event, formData)} // Trigger the handler on change | ||
| /> | ||
| ``` | ||
|
|
||
| ### 5. Calculating Computed Price | ||
|
|
||
| In addition to updating the input value of `numberOfFish`, we also want to update the value of `computedPrice`. We can do that by adding a helper function to run some logic to compute that value. We then call that helper function in the input's `onChange` handler: | ||
|
|
||
| This maps species to their respective prices: | ||
| ```jsx | ||
| const speciesPriceMap = { | ||
| grouper: 25.0, | ||
| salmon: 58.0, | ||
| marlin: 100.0, | ||
| mahimahi: 44.0, | ||
| }; | ||
| ``` | ||
|
|
||
| This function is kept outside the component since it doesn't rely on React state or lifecycle: | ||
| ```jsx | ||
| const computeFieldValue = (numberOfFish, species) => { | ||
| let computedPrice = parseInt(numberOfFish || 0) * parseInt(speciesPriceMap[species] || 0); | ||
| return computedPrice.toString(); | ||
| }; | ||
| ``` | ||
|
|
||
| This function updates the **Number of Fish** and dynamically computes the "Computed Price": | ||
| ```jsx | ||
| const handleNumberFishChange = (event, formData) => { | ||
| const { value } = event.target; | ||
| setFormData({ | ||
| ...formData, | ||
| [NUMBER_OF_FISH]: value, | ||
| [COMPUTED_PRICE]: computeFieldValue(value, formData?.species || ""), // Compute and update the "Computed Price" | ||
| }); | ||
| }; | ||
| ``` | ||
133 changes: 133 additions & 0 deletions
133
...eloper-documentation/examples-and-templates/examples/conditional-form-fields.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| --- | ||
| description: Dynamically show/hide fields based on other inputs | ||
| title: Conditional Form Fields | ||
| id: conditional-form-fields | ||
| --- | ||
|
|
||
| # Conditional Form Fields Example | ||
|
|
||
| This example shows you how to create a dynamic form with conditional fields. The visibility of certain input fields depends on the values of other fields. Specifically, when the `fullName` field is filled out, the `nickname` field becomes visible. If the `fullName` field is empty, the `nickname` field is hidden and removed from the `formState`. | ||
|
|
||
| Learn more about RADFish examples at the official [documentation](https://nmfs-radfish.github.io/radfish/developer-documentation/examples-and-templates#examples). Refer to the [RADFish GitHub repo](https://nmfs-radfish.github.io/radfish/) for more information and code samples. | ||
|
|
||
| ## Preview | ||
| This example will render as shown in this screenshot: | ||
|
|
||
|  | ||
|
|
||
|
|
||
| ## Steps | ||
|
|
||
| ### 1. Define Constants for Input Fields | ||
|
|
||
| Before building out your form, define constants for each input field. Using constants helps reduce errors and makes your logic more maintainable. | ||
|
|
||
| ```jsx | ||
| const FULL_NAME = "fullName"; | ||
| const NICKNAME = "nickname"; | ||
| ``` | ||
|
|
||
| In this example, we will build a form with two inputs. The value from `FULL_NAME` inputs will control the visiblity of `NICKNAME`. | ||
|
|
||
| ### 2. Initialize the Form Component with State | ||
|
|
||
| Next, we'll define the main form component. To manage the data entered in the form, we initialize it with a `formData` state variable, which is an empty object. This state will dynamically store the values of the form fields as users interact with the form. | ||
|
|
||
| The `setFormData` function allows us to update the state whenever an input changes. This ensures the form data is kept in sync. | ||
|
|
||
| ```jsx | ||
| const ConditionalForm = () => { | ||
| const [formData, setFormData] = useState({}); | ||
|
|
||
| return ( | ||
| // form JSX will go here | ||
| ); | ||
| }; | ||
| ``` | ||
|
|
||
| ### 3. Structuring the Form with Inputs | ||
|
|
||
| In the `return` statement of the component, use the Trussworks `Form` component to structure your form. Within the form, include input components such as `TextInput`, referencing the variables defined in Step 1 (e.g., `FULL_NAME`) instead of hardcoding strings. This practice helps avoid typos and ensures consistency when accessing the `formData` state. For better organization and styling, wrap your inputs within the `FormGroup` component provided by Trussworks. | ||
|
|
||
| ```jsx | ||
| return ( | ||
| <Form | ||
| onSubmit={handleSubmit} | ||
| className="maxw-full margin-205 padding-205 bg-white radius-8px shadow-2" | ||
| > | ||
| <FormGroup> | ||
| <Label className="text-bold" htmlFor={FULL_NAME}> | ||
| Full Name | ||
| </Label> | ||
| <TextInput | ||
| id={FULL_NAME} | ||
| name={FULL_NAME} | ||
| type="text" | ||
| placeholder="Full Name" | ||
| value={formData[FULL_NAME] || ""} | ||
| /> | ||
| ``` | ||
|
|
||
| ### 4. Adding Input Handlers for Form Fields | ||
|
|
||
| Now we can create an `onChange` handler for each input. This captures the input's value as it is being typed. We'll use `handleFullNameChange` to update state with a copy of the existing `formState`, and update only the field value that we want to update. In this case, the value we want to update is `fullName`. The value of this input will then re-render with the updated value from `formState`. | ||
|
|
||
| This function handles changes in the **Full Name** input field: | ||
| ```jsx | ||
| const handleFullNameChange = (event, formData) => { | ||
| const { value } = event.target; | ||
| setFormData({ | ||
| ...formData, // Preserve existing form data | ||
| [FULL_NAME]: value, // Update the "Full Name" field | ||
| }); | ||
| }; | ||
| ``` | ||
|
|
||
| Use the `handleFullNameChange` function to manage the **Full Name** input: | ||
| ```jsx | ||
| <TextInput | ||
| id={FULL_NAME} | ||
| name={FULL_NAME} | ||
| type="text" | ||
| placeholder="Full Name" | ||
| value={formData[FULL_NAME] || ""} | ||
| onChange={(event) => handleFullNameChange(event, formData)} // Call the handleFullNameChange function to update the "Full Name" field | ||
| /> | ||
| ``` | ||
|
|
||
| ### 5. Conditionally Render Nickname Field | ||
|
|
||
| Next, we want to conditionally render the `nickname` component. The condition depends on whether or not the `fullName` value is set in `formState`. This input field will only render if `formData[FULL_NAME]` evaluates to `true`. | ||
|
|
||
| ```jsx | ||
| { | ||
| formData[FULL_NAME] && ( | ||
| <> | ||
| <Label htmlFor={NICKNAME}>Nickname</Label> | ||
| <TextInput | ||
| id={NICKNAME} | ||
| name={NICKNAME} | ||
| type="text" | ||
| placeholder="Nickname" | ||
| value={formData[NICKNAME] || ""} | ||
| onChange={(event) => handleNickNameChange(event, formData)} | ||
| /> | ||
| </> | ||
| ) | ||
| } | ||
| ``` | ||
|
|
||
| ### 6. Managing Dependent Field Values | ||
|
|
||
| In this step, we ensure that the value of the **Nickname** field is cleared whenever the **Full Name** field is empty. Do this by adding logic to the `onChange` handler which calls the `handleFullNameChange` function. | ||
|
|
||
| ```jsx | ||
| const handleFullNameChange = (event, formData) => { | ||
| const { value } = event.target; | ||
| setFormData({ | ||
| ...formData, | ||
| [FULL_NAME]: value, | ||
| [NICKNAME]: value === "" ? "" : formData[NICKNAME], // Clear the "Nickname" field if "Full Name" is empty | ||
| }); | ||
| }; | ||
| ``` |
99 changes: 99 additions & 0 deletions
99
docs/developer-documentation/examples-and-templates/examples/field-validators.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| --- | ||
| description: Enforce validation logic, like disallowing numbers | ||
| title: Field Validators | ||
| id: field-validators | ||
| --- | ||
|
|
||
| # Form Field Validators Example | ||
|
|
||
| This example shows you how to enforce field validation logic on certain fields within your form. The validator ensures that no numbers are allowed within the **Full Name** input field. | ||
|
|
||
| Learn more about RADFish examples at the official [documentation](https://nmfs-radfish.github.io/radfish/developer-documentation/examples-and-templates#examples). Refer to the [RADFish GitHub repo](https://nmfs-radfish.github.io/radfish/) for more information and code samples. | ||
|
|
||
| ## Preview | ||
| This example will render as shown in this screenshot: | ||
|
|
||
|  | ||
|
|
||
| ## Steps | ||
|
|
||
| ### 1. Adding Validation with `onBlur` Handlers | ||
| In this step, we add validation logic to our form inputs using an `onBlur` handler. This ensures the data is validated when the user navigates away from the input field. It also provides immediate feedback on any validation errors. | ||
|
|
||
| This function validates the input value. It uses the validation rules and updates the state with any validation errors: | ||
| ```jsx | ||
| const handleBlur = (event, validators) => { | ||
| const { name, value } = event.target; | ||
| setValidationErrors((prev) => ({ | ||
| ...prev, | ||
| ...handleInputValidationLogic(name, value, validators), | ||
| })); | ||
| }; | ||
| ``` | ||
|
|
||
| This helper function loops through the provided validators and checks if the input value passes the validation criteria. If not, it returns the appropriate error message: | ||
| ```jsx | ||
| const handleInputValidationLogic = (name, value, validators) => { | ||
| if (validators && validators.length > 0) { | ||
| for (let validator of validators) { | ||
| if (!validator.test(value)) { | ||
| return { [name]: validator.message }; | ||
| } | ||
| } | ||
| } | ||
| return { [name]: null }; // Clear error if value is valid | ||
| }; | ||
| ``` | ||
|
|
||
| Here’s how to use the onBlur handler in the TextInput component. The input dynamically sets its validation status and ARIA attributes based on validation errors: | ||
| ```jsx | ||
| <TextInput | ||
| id={FULL_NAME} | ||
| name={FULL_NAME} | ||
| type="text" | ||
| placeholder="Full Name" | ||
| value={formData[FULL_NAME] || ""} | ||
| aria-invalid={validationErrors[FULL_NAME] ? "true" : "false"} | ||
| validationStatus={validationErrors[FULL_NAME] ? "error" : undefined} | ||
| onChange={handleChange} | ||
| onBlur={(e) => handleBlur(e, fullNameValidators)} | ||
| /> | ||
| ``` | ||
|
|
||
| ### 2. Testing with Validator | ||
| We include the validator needed to check the contents of the field input. In this case `fullNameValidators` has a single test that checks if the input contains a number. This array can include several tests for more complex validation logic. They are each included as separate objects within each validator array. | ||
|
|
||
| ```jsx | ||
| // utilities/fieldValidators.js | ||
| const fullNameValidators = [ | ||
| { | ||
| test: (value) => !/\d/.test(value) || value === "", | ||
| message: "Full Name should not contain numbers.", | ||
| }, | ||
| ]; | ||
|
|
||
| export { fullNameValidators }; | ||
|
|
||
| // in Form.js | ||
| import { fullNameValidators } from "../utilities/fieldValidators"; | ||
| ``` | ||
|
|
||
| ### 3. Trigger Validation Logic and Render Error Message | ||
| We can update the properties on our input so the validation logic gets triggered when a user navigates away from the form field. We also conditionally render an `ErrorMessage` when there is an error present. | ||
|
|
||
| ```jsx | ||
| <TextInput | ||
| id={FULL_NAME} | ||
| name={FULL_NAME} | ||
| type="text" | ||
| placeholder="Full Name" | ||
| value={formData[FULL_NAME] || ""} | ||
| aria-invalid={validationErrors[FULL_NAME] ? "true" : "false"} | ||
| validationStatus={validationErrors[FULL_NAME] ? "error" : undefined} | ||
| onChange={handleChange} | ||
| onBlur={(e) => handleBlur(e, fullNameValidators)} | ||
| /> | ||
| { | ||
| validationErrors[FULL_NAME] && <ErrorMessage>{validationErrors[FULL_NAME]}</ErrorMessage> | ||
| } | ||
| ``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this paragraph since it won't be referenced anymore. Will need to remove from the other .mds as well.