Skip to content

Commit ad69736

Browse files
fix: Add onFormStateChange callback on EventTypeSettings atom [CAL-5856] (calcom#21615)
* Adds onFormStateChange callback on EventTypeSettings atom * updated docs for event-type * added watch all form values --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
1 parent 8417192 commit ad69736

3 files changed

Lines changed: 34 additions & 1 deletion

File tree

docs/platform/atoms/event-type.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ export function EventTypeTabs(eventTypeId: number) {
131131
onSuccess={(eventType) => {
132132
console.log("EventType settings updated successfully", eventType);
133133
}}
134+
onFormStateChange={(formState) => {
135+
console.log("Form state changed:", formState);
136+
// Access form data: formState.isDirty, formState.dirtyFields, formState.values
137+
}}
134138
customClassNames={{ atomsWrapper: "!w-[70vw] !m-auto" }}
135139
/>
136140
</>
@@ -175,6 +179,7 @@ Below is a list of props that can be passed to the event type settings atom.
175179
| tabs | No | The tabs you want the event type settings to display |
176180
| onSuccess | No | Callback function that triggers when the event type is successfully updated |
177181
| onError | No | Callback function to handles errors at the time of event type update |
182+
| onFormStateChange | No | Callback function that triggers when the form state changes, providing access to isDirty, dirtyFields, and current form values |
178183
| onDeleteSuccess | No | Callback function that triggers when the event type is successfully deleted |
179184
| onDeleteError | No | Callback function that handles errors at the time of event type deletion | |
180185
| allowDelete | No | Boolean value that determines whether the delete button is displayed or not |

packages/platform/atoms/event-types/hooks/useEventTypeForm.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { zodResolver } from "@hookform/resolvers/zod";
2-
import { useMemo, useState } from "react";
2+
import { useMemo, useState, useEffect } from "react";
33
import { useForm } from "react-hook-form";
44
import { z } from "zod";
55

@@ -27,9 +27,15 @@ type Fields = z.infer<typeof eventTypeBookingFieldsSchema>;
2727
export const useEventTypeForm = ({
2828
eventType,
2929
onSubmit,
30+
onFormStateChange,
3031
}: {
3132
eventType: EventTypeSetupProps["eventType"];
3233
onSubmit: (data: EventTypeUpdateInput) => void;
34+
onFormStateChange?: (formState: {
35+
isDirty: boolean;
36+
dirtyFields: Partial<FormValues>;
37+
values: FormValues;
38+
}) => void;
3339
}) => {
3440
const { t } = useLocale();
3541
const [periodDates] = useState<{ startDate: Date; endDate: Date }>({
@@ -181,6 +187,19 @@ export const useEventTypeForm = ({
181187
formState: { isDirty: isFormDirty, dirtyFields },
182188
} = form;
183189

190+
// Watch all form values to trigger onFormStateChange on any change
191+
const watchedValues = form.watch();
192+
193+
useEffect(() => {
194+
if (onFormStateChange) {
195+
onFormStateChange({
196+
isDirty: isFormDirty,
197+
dirtyFields: dirtyFields as Partial<FormValues>,
198+
values: watchedValues,
199+
});
200+
}
201+
}, [isFormDirty, watchedValues, onFormStateChange]);
202+
184203
const isObject = <T>(value: T): boolean => {
185204
return value !== null && typeof value === "object" && !Array.isArray(value);
186205
};

packages/platform/atoms/event-types/wrappers/EventTypePlatformWrapper.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ export type EventTypePlatformWrapperProps = {
5757
customClassNames?: EventTypeCustomClassNames;
5858
disableToasts?: boolean;
5959
isDryRun?: boolean;
60+
onFormStateChange?: (formState: {
61+
isDirty: boolean;
62+
dirtyFields: Partial<FormValues>;
63+
values: FormValues;
64+
}) => void;
6065
};
6166

6267
const EventType = ({
@@ -70,6 +75,7 @@ const EventType = ({
7075
customClassNames,
7176
disableToasts = false,
7277
isDryRun = false,
78+
onFormStateChange,
7379
...props
7480
}: EventTypeSetupProps & EventTypePlatformWrapperProps) => {
7581
const { t } = useLocale();
@@ -150,6 +156,7 @@ const EventType = ({
150156
toast({ description: t("event_type_updated_successfully", { eventTypeTitle: eventType.title }) });
151157
}
152158
},
159+
onFormStateChange: onFormStateChange,
153160
});
154161
const slug = form.watch("slug") ?? eventType.slug;
155162

@@ -320,6 +327,7 @@ export const EventTypePlatformWrapper = ({
320327
allowDelete = true,
321328
customClassNames,
322329
isDryRun,
330+
onFormStateChange,
323331
}: EventTypePlatformWrapperProps) => {
324332
const { data: eventTypeQueryData } = useAtomsEventTypeById(id);
325333
const queryClient = useQueryClient();
@@ -352,6 +360,7 @@ export const EventTypePlatformWrapper = ({
352360
allowDelete={allowDelete}
353361
customClassNames={customClassNames}
354362
isDryRun={isDryRun}
363+
onFormStateChange={onFormStateChange}
355364
/>
356365
);
357366
};

0 commit comments

Comments
 (0)