LoginSignup
0
0

VanJSでお問い合わせフォームを作ってみた

Posted at

前回、公式のチュートリアルを触ってみましたが、今回は自分でお問い合わせフォームを作ってみたいと思います。
テキストインプット、ラジオボタン、セレクト、チェックボックス、テキストエリアの主要な入力フォームで作ってみます。

完成イメージ

001.png

作ってみる

環境準備

├── index.html
└── main.js
└── van-1.1.0.nomodule.min.js

今回は公式ドキュメントから.min.jsファイルをダウンロードして、ローカルでVanJSを読み込みます。

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

</body>
    <script type="text/javascript" src="van-1.1.0.nomodule.min.js"></script>
    <script src="main.js"></script>
</html>

お問い合わせフォームを作る

const {
  table,
  tbody,
  tr,
  th,
  td,
  form,
  div,
  input,
  select,
  option,
  label,
  textarea,
  button,
} = van.tags

const Form = () => {
  const name = van.state('')
  const sex = van.state('1')
  const prefecture = van.state('1')
  const mediaList = van.state([])
  const message = van.state('')

  const onsubmit = (e) => {
    e.preventDefault()

    console.log('送信', {
      name: name.val,
      sex: sex.val,
      prefecture: prefecture.val,
      mediaList: mediaList.val,
      message: message.val,
    })
  }

  return form(
    { onsubmit },
    table(
      tbody(
        tr(
          th('お名前'),
          td(
            // テキストインプット
            input({
              type: 'text',
              value: name,
              oninput: (e) => (name.val = e.target.value),
            }),
          ),
        ),
        tr(
          th('性別'),
          td(
            // ラジオボタン
            [
              { value: '1', label: '' },
              { value: '2', label: '' },
            ].map((item) =>
              div(
                input({
                  id: `sex${item.value}`,
                  type: 'radio',
                  value: item.value,
                  checked: () => item.value === sex.val,
                  onchange: (e) => (sex.val = e.target.value),
                }),
                label({ for: `sex${item.value}` }, item.label),
              ),
            ),
          ),
        ),
        tr(
          th('都道府県'),
          td(
            // セレクトボックス
            select(
              {
                value: prefecture,
                onchange: (e) => (prefecture.val = e.target.value),
              },
              // セレクトボックスのオプション
              [
                { value: '1', label: '北海道' },
                { value: '2', label: '青森県' },
                { value: '3', label: '岩手県' },
              ].map((item) => option({ value: item.value }, item.label)),
            ),
          ),
        ),
        tr(
          th('当社を何で知りましたか?'),
          td(
            // チェックボックス
            [
              { value: '1', label: 'テレビ' },
              { value: '2', label: '新聞' },
              { value: '3', label: 'SNS' },
            ].map((item) =>
              div(
                input({
                  id: `media${item.value}`,
                  type: 'checkbox',
                  value: item.value,
                  checked: () => mediaList.val.includes(item.value),
                  onchange: (e) => {
                    const { value, checked } = e.target

                    mediaList.val = checked
                      ? [...mediaList.val, value]
                      : mediaList.val.filter((media) => media !== value)
                  },
                }),
                label({ for: `media${item.value}` }, item.label),
              ),
            ),
          ),
        ),
        tr(
          th('お問い合わせ内容'),
          td(
            // テキストエリア
            textarea({
              rows: 10,
              value: message,
              oninput: (e) => (message.val = e.target.value),
            }),
          ),
        ),
      ),
    ),
    button({ type: 'submit' }, '送信'),
  )
}

van.add(document.body, Form())

注意点

van.state()で宣言した変数は、関数で書かないと動的に変わりません。例えばラジオボタンのcheckedchecked: item.value === sex.valだと、sex.valの値が動的に変わらないため、checked: () => item.value === sex.valのように記述する必要があります。

// ラジオボタン
[
  { value: '1', label: '' },
  { value: '2', label: '' },
].map((item) =>
  div(
    input({
      id: `sex${item.value}`,
      type: 'radio',
      value: item.value,
      // ❗関数で書く必要がある
      checked: () => item.value === sex.val,
      onchange: (e) => (sex.val = e.target.value),
    }),
    label({ for: `sex${item.value}` }, item.label),
  ),
),

ただし、value: nameのように.valを書いてなければ関数で書く必要はありません。

// テキストインプット
input({
  type: 'text',
  // ✅これは関数で書かなくてもOK
  value: name,
  oninput: (e) => (name.val = e.target.value),
}),

逆に、value: name.valだと、値が動的に変わらないため、例えば送信後にテキストの値を空にしようと、name.val = ''と書いてもinputの値は空になりません。

// テキストインプット
input({
  type: 'text',
  // ❌これだと動的に値が変わらない
  value: name.val,
  oninput: (e) => (name.val = e.target.value),
}),

まとめ

VanJSでお問い合わせフォームができました。感想ですが、JSXの感覚で書けるのでとても書きやすいです。Reactに慣れている方であれば学習コストも低いと思うのでおすすめです。

最後に

GoQSystemでは一緒に働いてくれる仲間を募集中です!

ご興味がある方は以下リンクよりご確認ください。

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