Skip to content

Commit a427574

Browse files
Add validation to belongsTo/hasOne/hasMany AutoRelationshipForms to ensure that they have valid react children
1 parent d8de673 commit a427574

File tree

5 files changed

+25
-6
lines changed

5 files changed

+25
-6
lines changed

packages/react/spec/auto/shadcn-defaults/inputs/form/ShadcnAutoRelationshipForm.stories.jsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,24 @@ const { Label } = elements;
1313

1414
const Component = (props) => {
1515
return (
16-
<AutoForm {...props} action={api.widget.create}>
16+
<AutoForm action={api.widget.create} {...props}>
1717
<div className="flex flex-col gap-4">
1818
<div>
19-
<AutoBelongsToForm field="section" primaryLabel="name"
19+
<AutoBelongsToForm
20+
field="section"
21+
primaryLabel="name"
2022
renderSelectedRecord={(record) => <Label>this is a custom belongsTo render for {record.name}</Label>}
2123
>
2224
<AutoInput field="name" />
2325
</AutoBelongsToForm>
2426
</div>
2527
<SubmitResultBanner />
26-
<AutoHasOneForm field="doodad" primaryLabel="name"
27-
secondaryLabel={(record) => `${record.weight ?? 'N/A'} (${record.active ?? 'N/A'})`} tertiaryLabel="size"
28+
<AutoHasOneForm
29+
field="doodad"
30+
primaryLabel="name"
31+
secondaryLabel={(record) => `${record.weight ?? "N/A"} (${record.active ?? "N/A"})`}
32+
tertiaryLabel="size"
2833
>
29-
3034
<div className="flex flex-col gap-4">
3135
<AutoInput field="name" />
3236
<AutoInput field="weight" />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Children } from "react";
2+
3+
export function useRequiredChildComponentsValidator(props: { children?: React.ReactNode }, componentName: string) {
4+
if (!props.children || Children.count(props.children) === 0) {
5+
throw new Error(`"${componentName}" requires child components`);
6+
}
7+
}

packages/react/src/auto/polaris/inputs/relationships/PolarisAutoHasManyForm.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { autoRelationshipForm } from "../../../AutoInput.js";
66
import { RelationshipContext, useAutoRelationship, useRelationshipContext } from "../../../hooks/useAutoRelationship.js";
77
import { useHasManyController } from "../../../hooks/useHasManyController.js";
88
import { getRecordAsOption, useOptionLabelForField } from "../../../hooks/useRelatedModel.js";
9+
import { useRequiredChildComponentsValidator } from "../../../hooks/useRequiredChildComponentsValidator.js";
910
import type { OptionLabel } from "../../../interfaces/AutoRelationshipInputProps.js";
1011
import { renderOptionLabel } from "./utils.js";
1112

@@ -18,6 +19,7 @@ export const PolarisAutoHasManyForm = autoRelationshipForm(
1819
secondaryLabel?: OptionLabel;
1920
tertiaryLabel?: OptionLabel;
2021
}) => {
22+
useRequiredChildComponentsValidator(props, "AutoHasManyForm");
2123
const { metadata } = useAutoRelationship({ field: props.field });
2224
const { getValues } = useFormContext();
2325

packages/react/src/useBelongsToForm.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1+
import { useEffect, useState } from "react";
12
import { useAutoRelationship, useRelationshipContext } from "./auto/hooks/useAutoRelationship.js";
23
import { useBelongsToController } from "./auto/hooks/useBelongsToController.js";
34
import { getRecordAsOption, useOptionLabelForField } from "./auto/hooks/useRelatedModel.js";
5+
import { useRequiredChildComponentsValidator } from "./auto/hooks/useRequiredChildComponentsValidator.js";
46
import type { OptionLabel } from "./auto/interfaces/AutoRelationshipInputProps.js";
57
import { useFormContext } from "./useActionForm.js";
68
import { get } from "./utils.js";
79

8-
import { useEffect, useState } from "react";
910
export const useBelongsToForm = (props: {
1011
field: string;
12+
children: React.ReactNode;
1113
primaryLabel?: OptionLabel;
1214
secondaryLabel?: OptionLabel;
1315
tertiaryLabel?: OptionLabel;
1416
}) => {
17+
useRequiredChildComponentsValidator(props, "AutoBelongsToForm");
1518
const { field } = props;
1619
const { path, metadata } = useAutoRelationship({ field });
1720
const {

packages/react/src/useHasOneForm.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useAutoRelationship, useRelationshipContext } from "./auto/hooks/useAutoRelationship.js";
22
import { useHasOneController } from "./auto/hooks/useHasOneController.js";
33
import { getRecordAsOption, useOptionLabelForField } from "./auto/hooks/useRelatedModel.js";
4+
import { useRequiredChildComponentsValidator } from "./auto/hooks/useRequiredChildComponentsValidator.js";
45
import type { OptionLabel } from "./auto/interfaces/AutoRelationshipInputProps.js";
56
import { useFormContext } from "./useActionForm.js";
67
import { get } from "./utils.js";
@@ -9,10 +10,12 @@ import { useEffect, useState } from "react";
910

1011
export const useHasOneForm = (props: {
1112
field: string;
13+
children: React.ReactNode;
1214
primaryLabel?: OptionLabel;
1315
secondaryLabel?: OptionLabel;
1416
tertiaryLabel?: OptionLabel;
1517
}) => {
18+
useRequiredChildComponentsValidator(props, "AutoHasOneForm");
1619
const { path, metadata } = useAutoRelationship({ field: props.field });
1720
const {
1821
setValue,

0 commit comments

Comments
 (0)