35
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

React + TypeScript + Ant Designでお問合せフォームを作る

Last updated at Posted at 2022-10-17

はじめに

本記事は、
「フロントエンドの開発効率を向上するヒントを教え合おう!」イベントの参加記事です。

前回、Reactの環境構築からAnt Designを適用させるところまで行いました。
今回はそこからお問合せフォームを簡単に作成していきたいと思います。

要件を決める

とりあえずお問合せフォームの例として、
「名前」、「性別」、「年齢」、「メールアドレス」、「都道府県」、「お問合せ内容」
これらを作成したいと思います。

以下のようなお問合せフォームを目指します。

image.png

お問合せフォームを実装する

前回と同じようにApp.tsxの中身を書き換えていきます。

それでは、細かい実装について順番に解説をしていきます。
※一番最後に完成版のソースコードを載せておきますので良くわからなくなったら、
そちらを見ていただいても良いかと思います。

まずはFormタグでお問合せフォームの大枠を作っていきます。
このタグで送信ボタンを押した時のonFinishと、フォームでのバリデーション時に表示するvalidateMessagesを渡しています。また、スプレット構文のlayoutで、labelとwrapperのサイズの指定も行っています。

function App() {

  const layout = {
    labelCol: {
      span: 8,
    },
    wrapperCol: {
      span: 8,
    },
  };

  const validateMessages = {
    required: '${label}は必須です。',
    types: {
      email: '${label}を正しい形式で入力してください。',
    },
    number: {
      range: '${label}は${min}から${max}の間で入力してください。',
    },
  };

  const onFinish = (item: string) => {
    console.log(item);
  };
return (
  <Form {...layout} name="nest-messages" onFinish={onFinish} validateMessages={validateMessages}>

次にフォーム内の項目についてですが、
FormタグのItemで作っていきます。

labelは項目名で、
rulesのrequiredは、そのままですが必須チェックの有無となります。
入力欄に関してはInputタグを用います。

  <Form.Item
    name={['user', 'name']}
    label="お名前"
    rules={[
      {
        required: true,
      },
    ]}
  >
    <Input />
  </Form.Item>

nameの指定を配列にすると、一つ目の要素は大枠のkeyとなり、
二つ目の要素に入力された値のkeyとなります。

以下がonFinishされた時のパラメータなのですが、
実際に確認すると分かりやすいですね。

{
    "user": {
        "name": "田中 太郎",
        "gender": 1,
        "age": 30,
        "email": "test@gmail.com",
        "prefecture": "東京都",
        "introduction": "これはテスト"
    }
}

requiredがtrueなので、入力がない場合はvalidateMessagesで定義したメッセージが適用され
以下のような形で表示されます。
labelの定義がそのまま当てはまるので便利ですね。

image.png

続いてラジオボタンの実装をしていきます。
Form.ItemタグのinitialValueで初期値を定義しています。
ラジオボタンは、Radio.Groupタグの内部にRadioタグを増やして実装していきます。

  <Form.Item
    name={['user', 'gender']}
    label="性別"
    initialValue={1}
    >
    <Radio.Group name="radiogroup">
      <Radio value={1}>男性</Radio>
      <Radio value={2}>女性</Radio>
      <Radio value={3}>その他</Radio>
    </Radio.Group>
  </Form.Item>

ちなみに初期値の定義としてRadio.Groupタグで
defaultValueを指定するというやり方もあるのですが…

<Radio.Group name="radiogroup" defaultValue={2}>

以下のメッセージのように推奨はされていないので、
初期値はinitialValueを使うようにしましょう。

arning: [antd: Form.Item] `defaultValue` will not work on controlled Field. You should use `initialValues` of Form instead.

次は年齢の入力です。
年齢入力に関しては、カレンダーや西暦で入力させた方が良いかとは思いますが、
今回は例なのでInputNumberを使っていきます。

これも見たままですが、
rulesでtypeにnumberを指定し、最小値と最大値を決めています。

  <Form.Item
    name={['user', 'age']}
    label="年齢"
    rules={[
      {
        type: 'number',
        min: 0,
        max: 150,
      },
    ]}
  >
    <InputNumber />
  </Form.Item>

エラーメッセージも以下のように表示されます。
こういう場合、そもそも期待値以外は入力できないようにするのがベターかと思いますが、
今回は例なので、悪しからず。

image.png

メールアドレスに関しては、typeにemailを指定しています。
あとは他とほぼ変わりません。

  <Form.Item
    name={['user', 'email']}
    label="メールアドレス"
    rules={[
      {
        type: 'email',
      },
    ]}
  >
    <Input />
  </Form.Item>

こちらもメールアドレスの形式に沿っていないと、
以下のようにエラーメッセージで怒られました。

image.png

入力項目の最後のお問合せ内容ですが、
こちらは文字をたくさん入力できるようにしたいので、InputタグのTextAreaを指定します。
これにより可変式のTextAreaが実装できます。

  <Form.Item name={['user', 'introduction']} label="お問合せ内容">
    <Input.TextArea />
  </Form.Item>

最後にボタンですが、antdのButtonタグを使用して、
typeにprimary、htmlTypeはsubmitを指定します。
wrapperは先ほど定義したlayoutと合わせて8としています。

  <Form.Item
    wrapperCol={{
      ...layout.wrapperCol,
      offset: 8,
    }}
  >
    <Button type="primary" htmlType="submit">
      送信
    </Button>

  </Form.Item>

完成

こちらが完成したソースコードになります。

App.tsx
import React from 'react';
import { Button, Form, Input, InputNumber, Radio } from 'antd';
import 'antd/dist/antd.css';
import Title from 'antd/lib/typography/Title';

function App() {

  const layout = {
    labelCol: {
      span: 8,
    },
    wrapperCol: {
      span: 8,
    },
  };

  const validateMessages = {
    required: '${label}は必須です。',
    types: {
      email: '${label}!を正しい形式で入力してください。',
    },
    number: {
      range: '${label}は${min}から${max}の間で入力してください。',
    },
  };

  const onFinish = (item: string) => {
    console.log(item);
  };

return (
  <div style={{margin: "50px"}}>
    <div style={{textAlign: "center"}}>
      <Title>お問合せフォーム</Title>
    </div>

    <Form {...layout} name="nest-messages" onFinish={onFinish} validateMessages={validateMessages}>

      <Form.Item
        name={['user', 'name']}
        label="お名前"
        rules={[
          {
            required: true,
          },
        ]}
      >
        <Input />
      </Form.Item>

      <Form.Item
        name={['user', 'gender']}
        label="性別"
        initialValue={1}
        >
        <Radio.Group name="radiogroup">
          <Radio value={1}>男性</Radio>
          <Radio value={2}>女性</Radio>
          <Radio value={3}>その他</Radio>
        </Radio.Group>
      </Form.Item>

      <Form.Item
        name={['user', 'age']}
        label="年齢"
        rules={[
          {
            type: 'number',
            min: 0,
            max: 150,
          },
        ]}
      >
        <InputNumber />
      </Form.Item>

      <Form.Item
        name={['user', 'email']}
        label="メールアドレス"
        rules={[
          {
            type: 'email',
          },
        ]}
      >
        <Input />
      </Form.Item>

      <Form.Item name={['user', 'prefecture']} label="都道府県">
        <Input />
      </Form.Item>

      <Form.Item name={['user', 'introduction']} label="お問合せ内容">
        <Input.TextArea />
      </Form.Item>

      <Form.Item
        wrapperCol={{
          ...layout.wrapperCol,
          offset: 8,
        }}
      >
        <Button type="primary" htmlType="submit">
          送信
        </Button>

      </Form.Item>
    </Form>
  </div>
  );
}

export default App;

まとめ

長くなりましたが、今回も簡単にお問合せフォームを実装できました。

ちなみに例えばですが、rulesのtypeは、Ant Design内のinterface.d.tsにて
RuleTypeで定義されたものが使用できるので詳しく知りたい方は、
定義の中身を読んでみてもいいかも知れません。

現状、Ant Designは日本語文献があまりないので、海外文献の翻訳か、
中身のコードを読まざるを得ないところは結構あります。(むしろ公式がサンプル集みたいな感じです)

ただ割と直感的に実装はできるので、
良かったら試してみてください。

参考

35
39
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
35
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?