PalmyraForm#

@palmyralabs/rt-forms · src/palmyra/form/PalmyraForm.tsx

Overview#

The root controlled form. Creates a FormManager via useFormManager(props), publishes it through FormManagerContext, forwards a StoreFactory through StoreFactoryContext, and wraps its children in a default FieldGroup name="_default". Field widgets inside the subtree self-register by consuming FieldGroupManagerContext — you never enumerate fields at the prop level.

Use PalmyraForm directly when you need full control of the submit / hydrate flow; for the common patterns, reach for PalmyraNewForm, PalmyraEditForm, or PalmyraViewForm.

Props — IFormOptions#

interface IFormOptions extends IStoreProps<StoreOptions & any> {
  children?:      any;
  formData?:      any;                // hydrate the form with this value
  onValidChange?: (isValid: boolean) => void;
}

interface IStoreProps<T> {
  storeFactory?: StoreFactory<any, T>;  // usually comes from StoreFactoryContext
  storeOptions?: T;
}

Ref — IForm#

interface IForm {
  getData(): any;
  setData(value: any): void;
  isValid(): boolean;
}

Example#

import { useRef } from 'react';
import { PalmyraForm, type IForm } from '@palmyralabs/rt-forms';
import { TextField } from '@palmyralabs/rt-forms-mantine';
import { Button } from '@mantine/core';

export function ManualUserForm() {
  const formRef = useRef<IForm>(null);

  const submit = async () => {
    if (!formRef.current?.isValid()) return;
    const data = formRef.current!.getData();
    // hand-rolled submit — skip PalmyraNewForm's automatic save
    await fetch('/api/palmyra/user', { method: 'POST', body: JSON.stringify(data) });
  };

  return (
    <>
      <PalmyraForm ref={formRef} onValidChange={v => console.log('valid?', v)}>
        <TextField attribute="loginName" label="Email" required />
        <TextField attribute="firstName" label="First name" />
        <TextField attribute="lastName"  label="Last name" />
      </PalmyraForm>
      <Button onClick={submit}>Submit</Button>
    </>
  );
}