Skip to content

Commit

Permalink
fix(DateTimeControl): consume data prop if present to populate edit f…
Browse files Browse the repository at this point in the history
…orms (#105)
  • Loading branch information
ashmortar authored Oct 23, 2024
1 parent 7f1994c commit fadef43
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 12 deletions.
63 changes: 56 additions & 7 deletions src/controls/DateTimeControl.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import { render } from "../common/test-render"
import { dateTimeSchema } from "../testSchemas/dateTimeSchema"
import { UISchema } from "../ui-schema"

const EXAMPLE_DATESTRING = "2021-08-09 12:34:56"
const USER_DATESTRING = EXAMPLE_DATESTRING.replace(" ", "")
const EMPTY_DATESTRING = ""
const INPUT_MASK = "YYYY-MM-DD HH:mm:ss"
const USER_NOTADATESTRING = "not a date"
const EXAMPLE_DATESTRING = "2021-08-09T12:34:56"
const RENDERED_DATESTRING = EXAMPLE_DATESTRING.replace("T", " ")
const USER_DATESTRING = EXAMPLE_DATESTRING.replace("T", "")
const TITLE = dateTimeSchema.properties.dateTime.title
const REQUIRED_TEXT = `${TITLE} is required`

test("renders the date that the user selects", async () => {
render({
Expand All @@ -17,7 +22,7 @@ test("renders the date that the user selects", async () => {
const input = await screen.findByLabelText(TITLE)
await userEvent.type(input, USER_DATESTRING)

await waitFor(() => expect(input).toHaveValue(EXAMPLE_DATESTRING))
await waitFor(() => expect(input).toHaveValue(RENDERED_DATESTRING))
})

test("renders default date when present", async () => {
Expand All @@ -33,7 +38,7 @@ test("renders default date when present", async () => {
},
})
const input = await screen.findByLabelText(TITLE)
expect(input).toHaveValue(EXAMPLE_DATESTRING)
expect(input).toHaveValue(RENDERED_DATESTRING)
})

test("updates jsonforms data as expected", async () => {
Expand All @@ -50,7 +55,7 @@ test("updates jsonforms data as expected", async () => {
await userEvent.click(screen.getByText("Submit"))
await waitFor(() => {
expect(data).toEqual({
dateTime: EXAMPLE_DATESTRING,
dateTime: RENDERED_DATESTRING,
})
})
})
Expand All @@ -65,7 +70,7 @@ test("renders required message if no value and interaction", async () => {
const input = await screen.findByLabelText(TITLE)
await userEvent.clear(input)
await userEvent.tab()
await screen.findByText(`${TITLE} is required`)
await screen.findByText(REQUIRED_TEXT)
})

test(" does not show required message if not requried", async () => {
Expand All @@ -76,7 +81,7 @@ test(" does not show required message if not requried", async () => {
await userEvent.clear(input)
await userEvent.tab()
await waitFor(() => {
expect(screen.queryByText(`${TITLE} is required`)).toBeNull()
expect(screen.queryByText(REQUIRED_TEXT)).toBeNull()
})
})

Expand Down Expand Up @@ -131,3 +136,47 @@ test("renders default props if invalid props are submitted", async () => {
// since our default doesn't show time
await screen.findByText("Today")
})

test("it does not error on failure to parse date", async () => {
render({
schema: {
...dateTimeSchema,
properties: {
dateTime: {
...dateTimeSchema.properties.dateTime,
format: "date-time",
default: EMPTY_DATESTRING,
},
},
},
})
const input = await screen.findByLabelText(TITLE)
await userEvent.type(input, USER_NOTADATESTRING)
await userEvent.tab()
await waitFor(() => {
expect(input).toHaveValue(EMPTY_DATESTRING)
})
})

test("it renders an input mask by default as user types", async () => {
render({
schema: dateTimeSchema,
})
const input = await screen.findByLabelText(TITLE)
await userEvent.click(input)
await waitFor(() => {
expect(input).toHaveValue(INPUT_MASK)
})
})

test("it renders form data for forms with existing values (edit)", async () => {
const data: Record<string, unknown> = {
dateTime: EXAMPLE_DATESTRING,
}
render({
schema: dateTimeSchema,
data,
})
const input = await screen.findByLabelText(TITLE)
expect(input).toHaveValue(RENDERED_DATESTRING)
})
35 changes: 30 additions & 5 deletions src/controls/DateTimeControl.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { memo } from "react"
import { memo, useCallback, useEffect } from "react"
import type { ControlProps as JSFControlProps } from "@jsonforms/core"
import { withJsonFormsControlProps } from "@jsonforms/react"
import { DatePicker, type DatePickerProps, Form } from "antd"
Expand Down Expand Up @@ -26,6 +26,19 @@ function getProps(options: unknown): DateTimeControlOptions {
return DEFAULT_PROPS
}

function getInitialValue(
data: unknown,
schemaDefault: unknown,
): string | undefined {
if (typeof data === "string" && data !== "") {
return data
}
if (typeof schemaDefault === "string" && schemaDefault !== "") {
return schemaDefault
}
return undefined
}

export function DateTimeControl({
handleChange,
path,
Expand All @@ -35,12 +48,25 @@ export function DateTimeControl({
schema,
uischema,
visible,
data,
}: ControlProps) {
const setInitialValue = useCallback(
(value: string | undefined) => {
const coercedValue = value ? dayjs(value) : value
handleChange(path, value)
return coercedValue
},
[handleChange, path],
)
const form = Form.useFormInstance()
useEffect(() => {
form.setFieldValue(
path,
setInitialValue(getInitialValue(data, schema.default)),
)
}, [data, form, path, schema.default, setInitialValue])
if (!visible) return null

const initialValue =
typeof schema.default === "string" ? dayjs(schema.default) : undefined

const rules: Rule[] = [{ required, message: `${label} is required` }]

const formItemProps =
Expand All @@ -60,7 +86,6 @@ export function DateTimeControl({
required={required}
validateTrigger={["onBlur"]}
rules={rules}
initialValue={initialValue}
{...formItemProps}
>
<DatePicker
Expand Down
11 changes: 11 additions & 0 deletions src/stories/controls/DateTimeControl.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,14 @@ export const DefaultValue: Story = {
uiSchema: dateTimeUISchema,
},
}

export const ExistingValue: Story = {
tags: ["autodocs"],
args: {
jsonSchema: dateTimeSchema,
uiSchema: dateTimeUISchema,
data: {
dateTime: "1999-12-31T23:59:59.999Z",
},
},
}

0 comments on commit fadef43

Please sign in to comment.