javascriptでselectboxとinput type="text"を連動させる方法

プルダウンとテキスト入力欄を連動させたい

プルダウンを選択したら入力欄を自動的に補完したいということがあると思います。
一個くらいなら決め打ちでもいいのですが、複数あるとなかなか面倒なのでまとめてonchangeに登録する方法も書いてみます。
環境としてはphpはあまり関係ありませんが、javascriptはes6以上で書いてます。
es6より前のverの場合はletやconstをvarに、for~ofはforEachなどに読み替えてください。

まずは一個の場合から

HTML

<body>
<form action="/test_next.php" method="post">
    <table>
        <tr>
            <th>商品名</th>
            <th>値段</th>
        </tr>
        <tr>
            <td><select name="itemName" title="itemName">
            <?php foreach ($items as $item) : ?>
            <option value="<?= $item['price'] ?>"><?= $item['name'] ?></option>
            <?php endforeach; ?>
            </select></td>
            <td><input type="text" value="" name="price"></td>
        </tr>
    </table>
    <button type="submit">送信</button>
</form>
</body>

PHP

<?php
$items = [
    [ 'id' => 1,
    'name' => 'Macbookpro',
    'price' => '150000'],
    [ 'id' => 2,
    'name' => 'Switch',
    'price' => '15000'],
    [ 'id' => 3,
    'name' => 'PS4',
    'price' => '25000'],
];
?>

javascript

これに対してselectboxとtextを連動させようと思います。

let itemName = document.querySelector('[name="itemName"]');
let price = document.querySelector('[name="price"]');
itemName.onchange = function () {
    price.value = itemName.value;
}

解説

HTMLの段階でoptionのvalueに入力欄に入れたい値をすでに設定しているので、
selectboxの選択済みの値を<select>要素のvalueから取得しています。
取得した値を入力欄のvalueにしておしまいです。

複数ある場合

HTML

<form action="/test_next.php" method="post">
    <table>
        <tr>
            <th>チェック</th>
            <th>商品名</th>
            <th>値段</th>
        </tr>
        <?php foreach ($users as $user) : ?>
        <tr data-name="item-list" id="<?= $user['id'] ?>">
            <td><input type="checkbox" value="1"></td>
            <td><select name="itemName[<?= $user['id'] ?>]">
            <?php foreach ($items as $item) : ?>
            <option value="<?= $item['price'] ?>"><?= $item['name'] ?></option>
            <?php endforeach; ?>
            </select></td>
            <td><input type="text" value="" name="price[<?= $user['id'] ?>]"></td>
        </tr>
        <?php endforeach; ?>
    </table>
    <button type="submit">送信</button>
</form>

PHP

<?php
<?php
$items = [
    [ 'id' => 1,
    'name' => 'Macbookpro',
    'price' => '150000'],
    [ 'id' => 2,
    'name' => 'Switch',
    'price' => '15000'],
    [ 'id' => 3,
    'name' => 'PS4',
    'price' => '25000'],
];
$users = [
    [ 'id' => 1,
    'name' => 'Mike'],
    [ 'id' => 2,
    'name' => 'Kuro']
];
?>

javascript

今回はミケさんとクロさんの二人のユーザに対してそれぞれフォームが用意されています。
ミケさんのプルダウンが選択されたらミケさんの入力欄が、クロさんのプルダウンが選択されたらクロさんの入力欄が補完されるようにしたいと思います。

let itemList = document.querySelectorAll('[data-name="item-list]');
for (const item of itemList) {
    let itemName = item.querySelector('[name="itemName[' + item.id + ']"]');
    let price = item.querySelector('[name="price[' + item.id + ']"');
    itemName.onchange = function () {
        price.value = itemName.value;
    }
}

解説

一個しかない場合に対して複数ある場合は一旦trタグの要素を取得しています。
カスタムデータ属性を指定することで複数の要素をまとめて取得してfor文で回しています。
あとはquerySelectorのnameの箇所に各ユーザのidを埋め込んで、それ以外は一個しかない場合と同じです。

最後に

他にももっといい方法や、ここはもっとこうした方が良いなどの意見がある方はコメントにて頂けますと幸いです。

編集履歴

  • selectboxで一つしか選択しない場合はselectのvalueで選択済みの値を取得できるよう修正。 ※selectboxにmultipleをつけている場合はfor分でselectboxの中身を回覧する必要があります。
  • 複数ある場合、class名で複数要素を取得していたが、微妙なのでカスタムデータ属性に修正。
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.