Build a field editor directly into a page
Let a signed-in customer edit a complaint draft on their dashboard without rebuilding document state or nested field paths.
This generated recipe is review-ready source material. Use it from the runtime where it appears in the sidebar and search results.
Let a signed-in customer edit a complaint draft on their dashboard without rebuilding document state or nested field paths.
Use this when
- build a custom field editor in my app
- edit a dyrected document inside a customer dashboard
- mount dyrected form state in a customer route
- edit nested customer complaint fields without the admin page
Dyrected concepts
createDyrectedFormController, DyrectedFormProvider, DyrectedFieldPathProvider, useDyrectedForm, useField
Additional packages: @dyrected/admin, @dyrected/react
Decisions and cautions
Use this recipe only when its runtime matches the project you are documenting or building. Cloud recipes must stay inside the managed content backend boundary. Self-hosted recipes may use the server runtime, database, hooks, and infrastructure you control.
Complete recipe
This is the canonical source compiled and behavior-tested by @dyrected/knowledge.
import {
DyrectedFieldPathProvider,
DyrectedFormProvider,
useDyrectedForm,
useField,
} from "@dyrected/react";
import { createDyrectedFormController } from "@dyrected/admin/public";
const controller = createDyrectedFormController({
collection: "customers",
fields: [
{ name: "fullName", type: "text", label: "Full name" },
{ name: "email", type: "email", label: "Email address" },
{
name: "complaintDraft",
type: "object",
label: "Complaint draft",
fields: [
{ name: "orderNumber", type: "text", label: "Order number" },
{ name: "subject", type: "text", label: "Subject" },
{ name: "message", type: "textarea", label: "Complaint message" },
],
},
],
initialValues: {
fullName: "Amara Okafor",
email: "[email protected]",
complaintDraft: {
orderNumber: "ORD-2048",
subject: "Damaged package on arrival",
message: "The shipping box arrived wet and the product inside is scratched.",
},
},
});
function CustomerIdentityCard() {
const fullName = useField("fullName");
const email = useField("email");
return (
<section className="space-y-4">
<input
value={String(fullName.value ?? "")}
onChange={(event) => fullName.setValue(event.target.value)}
/>
<input
type="email"
value={String(email.value ?? "")}
onChange={(event) => email.setValue(event.target.value)}
/>
</section>
);
}
function ComplaintDraftEditor() {
const orderNumber = useField("orderNumber");
const subject = useField("subject");
const message = useField("message");
return (
<section className="space-y-4">
<input
value={String(orderNumber.value ?? "")}
onChange={(event) => orderNumber.setValue(event.target.value)}
/>
<input
value={String(subject.value ?? "")}
onChange={(event) => subject.setValue(event.target.value)}
/>
<textarea
value={String(message.value ?? "")}
onChange={(event) => message.setValue(event.target.value)}
/>
</section>
);
}
function CustomerComplaintPage() {
const form = useDyrectedForm();
return (
<form
className="space-y-6"
onSubmit={(event) => {
event.preventDefault();
void form.submit();
}}
>
<h1>Complaint draft for signed-in customer</h1>
<CustomerIdentityCard />
<DyrectedFieldPathProvider path="complaintDraft">
<ComplaintDraftEditor />
</DyrectedFieldPathProvider>
<button type="submit" disabled={form.isSubmitting}>
Save complaint draft
</button>
</form>
);
}
export default function CustomerComplaintRoute() {
return (
<DyrectedFormProvider controller={controller}>
<CustomerComplaintPage />
</DyrectedFormProvider>
);
}