Skip to content

Instantly share code, notes, and snippets.

@tyteen4a03
Last active January 3, 2025 16:31
Show Gist options
  • Save tyteen4a03/2708e1b57c8f2c904032cc1cceb9b007 to your computer and use it in GitHub Desktop.
Save tyteen4a03/2708e1b57c8f2c904032cc1cceb9b007 to your computer and use it in GitHub Desktop.
PayloadCMS Listener Field Pattern (v3)
{
name: "jobStopsListener",
type: "ui",
admin: {
components: {
Field: "@/modules/transport/components/JobStopsListenerField",
},
},
},
import JobStopsListenerFieldEffect from "@/modules/transport/components/JobStopsListenerField/JobStopsListenerFieldEffect";
import type { UIFieldServerComponent } from "payload";
const JobStopsListenerField: UIFieldServerComponent = async ({ payload }) => {
const warehouse =
(
await payload.find({
collection: "addresses",
where: {
type: {
equals: "warehouse",
},
},
limit: 1,
})
).docs[0] ?? null;
if (!warehouse) {
return null;
}
return <JobStopsListenerFieldEffect warehouse={warehouse} />;
};
export default JobStopsListenerField;
"use client";
import type { Address, Job } from "@/payload-types";
import { useField, useForm } from "@payloadcms/ui";
import { useEffect } from "react";
interface JobStopsListenerFieldEffectProps {
warehouse: Address | null;
}
const JobStopsListenerFieldEffect = ({ warehouse }: JobStopsListenerFieldEffectProps) => {
const { getDataByPath, addFieldRow } = useForm();
/**
* For some reason, `useForm()`'s `initializing` returns `true` before the entire form finishes rendering.
* Using `useField()`'s `formInitializing` is more reliable, as it checks that the entire form has finished
* rendering, instead of whether the renderer has finished rendering up to the listener field's position.
*/
const { formInitializing } = useField({
path: "",
});
const stopsField: Job["stops"] = getDataByPath("stops");
useEffect(() => {
// Don't run if form is still initializing
if (formInitializing) {
return;
}
const inner = async () => {
if (warehouse && stopsField?.length === 0) {
// insert Warehouse as the first row, if no stops exist
addFieldRow({
subFieldState: {
address: { initialValue: warehouse.id, value: warehouse.id, valid: true },
contactName: { initialValue: warehouse.contactName, value: warehouse.contactName, valid: true },
contactPhoneNumber: {
initialValue: warehouse.contactPhoneNumber,
value: warehouse.contactPhoneNumber,
valid: true,
},
},
path: "stops",
schemaPath: "jobs.stops",
});
}
};
void inner();
}, [warehouse, stopsField, addFieldRow, formInitializing]);
return <></>;
};
export default JobStopsListenerFieldEffect;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment