AppForm

A themed native form that keeps field composition, validation and submission in your control.

AppForm

View source · API reference

Save a project

Edit the project name, save it locally, then reset. The handler explicitly checks native constraints because AppForm renders novalidate.

<RegorApp id="app-form-demo" src="./playground.ts"/>
import {
  defineButtonComponents,
  defineFlexComponents,
  defineFormComponents,
  defineFormInputField,
  definePanelComponents,
} from '@purestack/ts-components'

import { createApp, defineComponent, html, type Ref, ref } from 'regor'

export interface AppFormExample {
  projectName: Ref<string>
  savedProject: Ref<string>
  save: (event: Event) => void
  reset: () => void
}

const appFormExampleTemplate = html`<Panel bodyClass="p-4">
  <AppForm @submit.prevent="save" @reset.prevent="reset">
    <FormInputField
      id="app-form-project"
      name="project"
      label="Project name"
      :model="projectName"
      :required="true"
      minlength="3"
    />
    <FormMeta>
      <FormSubmit label="Save project" tone="accent" />
      <Btn type="reset" variant="outline">Reset</Btn>
    </FormMeta>
    <FormStatus tone="success" :hidden="!savedProject">
      Saved locally: {{ savedProject }}
    </FormStatus>
  </AppForm>
</Panel>`

function createAppFormExample(): AppFormExample {
  const projectName = ref('Studio docs')
  const savedProject = ref('')
  return {
    projectName,
    savedProject,
    save: (event) => {
      const form = event.target as HTMLFormElement
      if (!form.reportValidity()) return
      savedProject(String(new FormData(form).get('project') ?? ''))
    },
    reset: () => {
      projectName('Studio docs')
      savedProject('')
    },
  }
}

const component = defineComponent<AppFormExample>(appFormExampleTemplate, {
  context: createAppFormExample,
})

createApp(
  {
    components: {
      AppFormExample: component,

      ...defineFlexComponents(),
      ...definePanelComponents(),
      ...defineButtonComponents(),
      ...defineFormComponents(),
      ...defineFormInputField(),
    },
  },
  { selector: 'app#app-form-demo', template: html`<AppFormExample />` },
)

Compose a form surface

Choose the surrounding treatment independently of the fields. This disabled example shows structure without submitting data.

Connect the form to your application’s submit handler.
<AppForm method="post" tone="neutral" variant="outline" class="p-4">
  <FormInputField
    id="form-structure-name"
    name="name"
    label="Workspace name"
    placeholder="Your workspace"
    :disabled="true"
  />
  <FormStatus>Connect the form to your application’s submit handler.</FormStatus>
</AppForm>

Behavior and accessibility

AppForm always renders novalidate. Use reportValidity or your own validation in a submit handler. Named controls participate in FormData; disabled controls do not. Reset reactive refs explicitly when handling reset in a Regor app.

API reference

AppForm contract

Props below are the public template API. RefOrValue accepts a literal or a reactive ref; bind refs with a colon-prefixed attribute. Native attributes and events can be passed through the component root.

action

RefOrValue<string>
Default
not set

Native submission URL, resolved against the SSG base path. Browser examples intercept submit to keep data local.

method

RefOrValue<string>
Default
browser default: get

Native form method. Set post when your endpoint expects a request body.

tone

RefOrValue<SemanticTone>
Default
inherited

Semantic intent: neutral, accent, secondary, info, success, warning, danger, feature, custom or ghost. The active skin supplies the colors.

variant

RefOrValue<ComponentVariant>
Default
none

Visual treatment. Accepts solid, surface, surfaceAlt, spotlight, glass, flat, flatAlt, flatSolid, outlineFill, outline, subtle, subtleBtn, link, sheen, underline, rail, bracket or none.

Composition

Default slot: native fields and form components. Native submit and reset events bubble normally. Register defineFormComponents; register each field family separately.