0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SolidJSAdvent Calendar 2024

Day 9

solidjsでも使えるformライブラリ「modular-forms」の紹介

Posted at

この記事は、SolidJSアドベントカレンダー 2024 9日目の記事です。

フォームライブラリ

現状私が確認してる限りではsolidjsで使えるフォームライブラリは以下の2つです。

  • modular-forms
  • @solid-mediakit/form

ドキュメントが充実してたのでmodular-formsを触ってみました。

概要

  • デフォルトではuncontrolled、controlledへの移行も簡単
  • validationではzodだけでなくvalibotも対応
  • ArrayやObjectの形式の構成も可能
  • Actionsは残念ながら非対応
    • FAQの「Does it work with SolidStart?」参照

使い方

導入

pnpm install modular-forms/solid

フォーム実装

getValueを "@modular-forms/solid" からimportしているように、react-hook-form等とは違い細かい関数はimportする必要があります。(バンドルサイズを減らすため)

import { createForm, getValues, insert, valiForm } from "@modular-forms/solid";
import * as v from "valibot";

const LoginSchema = v.object({
  username: v.string(),
  password: v.string(),
});

export default function Page() {
  const [form, { Form, Field }] = createForm<SpecialForm>({
    validate: valiForm(LoginSchema),
  });
  createEffect(() => {
    console.log(getValues(form));
  });
  return (
    <div>
      <h1>Modular Forms</h1>
      <Form onSubmit={(v)=>{console.log(v)}}>
        <Field name="username" >
          {(field, props) => <input {...props}  />}
        </Field>
        <Field name="password" >
          {(field, props) => <input type="password" {...props}  />}
        </Field>
        <button type="submit">Submit</button>
      </Form>
    </div>
  );
}

その他

Controlled

デフォルトではuncontrolledなのでcontrolledにする場合はfield.valueをvalueに渡す

        <Field name="username" >
          {(field, props) => <input value={field.value} {...props}  />}
        </Field>

Error表示

        <Field name="username" >
          {(field, props) => {
            return <div>
              <input {...props} />
              <div>{field.error}</div>
            </div>;
          }}
        </Field>

FieldArray

// ↓こんな感じのフォームのとき
const LoginSchema = v.object({
  list: v.array(v.object({ value: v.string() }))
});
// ↓フォームはこうなる
        <FieldArray name="list">
          {(fieldArray) => (
            <>
              <For each={fieldArray.items}>
                {(item, index) => (
                  <div>
                    <Field name={`list.${index()}.value`}>
                      {(field, props) => <input {...props} type="text" />}
                    </Field>
                  </div>
                )}
              </For>
              <button
                type="button"
                onClick={() => insert(form, "list", { value:{ value: "" } })}
              >
                Add
              </button>
            </>
          )}
        </FieldArray>

Custom Input

必要なプロパティをcontextで引き回してあげるとシンプルに実装できる

import {
  Field as BaseField,
  type FormStore,
  createForm,
  valiForm,
} from "@modular-forms/solid";
import { Show, createContext, useContext } from "solid-js";
import * as v from "valibot";

const LoginSchema = v.object({
  username: v.string(),
});

type LoginForm = v.InferInput<typeof LoginSchema>;

const formContext = createContext<FormStore<LoginForm>>();

const UserName = () => {
  const context = useContext(formContext);
  return (
    <Show when={context}>
      {(form) => {
        return (
          <BaseField name="username" of={form()}>
            {(field, props) => {
              return (
                <>
                  <input {...props} />
                  {field.error}
                </>
              );
            }}
          </BaseField>
        );
      }}
    </Show>
  );
};

export default function Page() {
  const [form, { Form, Field, FieldArray }] = createForm<LoginForm>({
    validate: valiForm(LoginSchema),
  });
  return (
    <div>
      <h1>Modular Forms</h1>
      <formContext.Provider value={form}>
        <Form
          onSubmit={(v) => {
            console.log(v);
          }}
        >
          <UserName />
          <button type="submit">Submit</button>
        </Form>
      </formContext.Provider>
    </div>
  );
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?