# AkiForm

It provides a seamless way to build type-safe, validated forms with minimal boilerplate.

### <mark style="color:red;">Installation</mark>

```bash
pnpm add @akinon/akiform
```

For schema-driven form building, also install:

```bash
pnpm add @akinon/akiform-builder
```

### <mark style="color:red;">Core Concepts</mark>

Akiform offers two approaches:

1. **Component-based** - Use `Akiform` and `FormItem` components with React Hook Form hooks
2. **Schema-driven** - Use `AkiformBuilder` with a declarative field schema

### <mark style="color:red;">Component-Based Usage</mark>

#### Basic Form

```tsx
import { Akiform, FormItem, useForm } from '@akinon/akiform';
import { akival, akivalResolver } from '@akinon/akiform';
import { Input } from '@akinon/ui-input';
import { Button } from '@akinon/ui-button';

interface LoginForm {
  email: string;
  password: string;
}

const validationSchema = akival.object({
  email: akival.string().email().required(),
  password: akival.string().min(8).required()
});

export const LoginForm = () => {
  const { control, handleSubmit } = useForm<LoginForm>({
    resolver: akivalResolver(validationSchema),
    defaultValues: {
      email: '',
      password: ''
    }
  });

  const onSubmit = (data: LoginForm) => {
    console.log('Form submitted:', data);
  };

  return (
    <Akiform layout="vertical" onFinish={handleSubmit(onSubmit)}>
      <FormItem control={control} name="email" label="Email">
        <Input placeholder="Enter email" />
      </FormItem>
      <FormItem control={control} name="password" label="Password">
        <Input type="password" placeholder="Enter password" />
      </FormItem>
      <Button type="primary" htmlType="submit">
        Sign In
      </Button>
    </Akiform>
  );
};
```

#### FormItem Props

| Prop               | Type                     | Description                                           |
| ------------------ | ------------------------ | ----------------------------------------------------- |
| `control`          | `Control<T>`             | React Hook Form control object                        |
| `name`             | `FieldPath<T>`           | Field name/path in the form data                      |
| `label`            | `string`                 | Field label                                           |
| `labelDescription` | `string`                 | Additional description below label                    |
| `help`             | `string`                 | Help text below input                                 |
| `tooltip`          | `TooltipProps \| string` | Tooltip for the label                                 |
| `disabled`         | `boolean`                | Disable the field                                     |
| `valuePropName`    | `string`                 | Custom value prop name (e.g., `checked` for checkbox) |

#### Akiform Props

| Prop                 | Type                                     | Default        | Description                 |
| -------------------- | ---------------------------------------- | -------------- | --------------------------- |
| `layout`             | `'horizontal' \| 'vertical' \| 'inline'` | `'horizontal'` | Form layout                 |
| `labelAlign`         | `'left' \| 'right'`                      | -              | Label text alignment        |
| `labelCol`           | `ColProps`                               | -              | Label column layout         |
| `wrapperCol`         | `ColProps`                               | -              | Input wrapper column layout |
| `size`               | `'small' \| 'middle' \| 'large'`         | -              | Form controls size          |
| `disabled`           | `boolean`                                | -              | Disable all form fields     |
| `colon`              | `boolean`                                | -              | Show colon after label      |
| `scrollToFirstError` | `boolean \| Options`                     | -              | Auto scroll to first error  |

### <mark style="color:red;">Hooks</mark>

#### useForm

Create a form instance with React Hook Form:

```tsx
import { useForm, type UseFormProps } from '@akinon/akiform';

const { control, handleSubmit, reset, watch, setValue, getValues, formState } = 
  useForm<FormValues>({
    defaultValues: {
      name: '',
      email: ''
    },
    resolver: akivalResolver(schema)
  });
```

#### useWatch

Watch form values reactively:

```tsx
import { useWatch } from '@akinon/akiform';

const FormComponent = ({ control }) => {
  const watchedValue = useWatch({ control, name: 'fieldName' });
  const allValues = useWatch({ control });
  
  return <div>Current value: {watchedValue}</div>;
};
```

#### useController

Access field state and methods:

```tsx
import { useController } from '@akinon/akiform';

const CustomInput = ({ control, name }) => {
  const { field, fieldState } = useController({ control, name });
  
  return (
    <div>
      <input {...field} />
      {fieldState.error && <span>{fieldState.error.message}</span>}
    </div>
  );
};
```

#### useFieldArray

Manage dynamic field arrays:

```tsx
import { useFieldArray } from '@akinon/akiform';

const DynamicFields = ({ control }) => {
  const { fields, append, remove } = useFieldArray({
    control,
    name: 'items'
  });
  
  return (
    <div>
      {fields.map((field, index) => (
        <div key={field.id}>
          <FormItem control={control} name={`items.${index}.name`}>
            <Input />
          </FormItem>
          <Button onClick={() => remove(index)}>Remove</Button>
        </div>
      ))}
      <Button onClick={() => append({ name: '' })}>Add Item</Button>
    </div>
  );
};
```

### <mark style="color:red;">Validation with Akival</mark>

Use `@akinon/akival` for form validation:

```tsx
import { akival, akivalResolver } from '@akinon/akiform';

const schema = akival.object({
  username: akival.string()
    .min(3, 'Username must be at least 3 characters')
    .required('Username is required'),
  email: akival.string()
    .email('Invalid email format')
    .required('Email is required'),
  age: akival.number()
    .min(18, 'Must be at least 18')
    .required('Age is required')
});

const { control } = useForm({
  resolver: akivalResolver(schema)
});
```

### <mark style="color:red;">DevTools</mark>

Enable form debugging in development:

```tsx
import { AkiformDevTool } from '@akinon/akiform';

const Form = () => {
  const { control } = useForm();
  
  return (
    <>
      <Akiform>
        {/* form fields */}
      </Akiform>
      {process.env.NODE_ENV === 'development' && (
        <AkiformDevTool control={control} />
      )}
    </>
  );
};
```

### <mark style="color:red;">Best Practices</mark>

1. **Type your forms** - Always define TypeScript interfaces for form values
2. **Use** [**Akival**](/akinon-ui/ui-kit/utilities/akival.md) **for validation** - Consistent validation with meaningful error messages
3. **Provide default values** - Always initialize form with `defaultValues`
4. **Use FormItem for integration** - Seamless error handling with Ant Design styling

### <mark style="color:red;">Related</mark>

* [AkiformBuilder](/akinon-ui/ui-kit/components/akiform-builder.md) - Schema-driven form builder for declarative form definitions
* [Akival](/akinon-ui/ui-kit/utilities/akival.md) - Validation library for form validation


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akinon.com/akinon-ui/ui-kit/components/akiform.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
