先日Jqueryを使って、フォームの値などを操作していたのですが、気になる現象が発生しました。
送信ボタンが複数ある、ちょっと複雑なフォームだったのですが、動かしてみると、予期せず複数フォームに同じ値がセットされていました。
これは具合が悪いとおもい、しらべ対処いたしました。
今回も忘備録として記録いたします。
やりたいこと
複数フォームがあり、入力フォームに値をいれて、ボタンを押したら出力部分に値を反映するというものです。
※サンプルでは、出力部分は普通のフォームですが、実際には非表示フォームです。
現象:実際にやってみたらこうなりました。
入力部分01で入力した値が、出力01、出力02両方に反映されてしまいました。
サンプルで試していただくと、入力01、入力02で入力した値が、両方の出力に同時反映されてしまいます。
入力と出力を分離しているのでそれぞれのフォームに反映できないと困ります。
早速原因を調べてみました。
なぜ複数フォームに同時に反映されてしまうのか?
今回の仕掛けはこのようになっています。
- 入力フォームのボタンを押したら入力フォームの値を取り出す。
- 取り出した値を出力フォームにセットする
これらのことをJqueryで行っていますが、あることに気づきました。
出力フォーム01と02の名前が同じ
なるほど、同じ名前だから、出力時に同時に反映されるのだと。
対処方法
対処方法としては以下の3つが考えられます。
- フォームの「name」をそれぞれ違う名前にする
- フォームに異なる名称の「クラス」を設定する
- Jqueryで頑張って区別する
1と2はフォームに異なる名前を付けるので、物理的に区別することができます。
実際にフォームが少ない場合はこちらのほうが現実的です。
でも、フォームが100個あるなど多数の場合は、1、2の方法はあまり現実的ではありません。
なぜならば、メンテナンスがものすごく大変だからです。
つまり、nameやクラスが異なっていものが100以上あると、Jquery側にも100種類以上の記述が必要になるためです。
例えば、さらに100個追加となった場合に、Jquery側も直さなければいけません。
これは面倒だと思い、3の方法で何とかすることにしました。
直した方法はこちら
直す前のJquery部分がこちらです。
<script>
$(document).ready(function()
{
$('input[name="input_set"]').click(function()
{
var value = $(this).parent("div").children('input[name=input]').val();
$('input[name="output"]').val(value);
});
});
</script>
name=”output” に値をセットしています。
これだと当然、同じ名前すべてにセットされます。
そこで次のように変えました。
ボタンを押された親のformをだどり、その子供のoutputフォームにセットする
そのソースがこちらです。
<script>
$(document).ready(function()
{
$('input[name="input_set"]').click(function()
{
var value = $(this).parent("div").children('input[name=input]').val();
$(this).parent("div").parent("form").children("div").children('input[name="output"]').val(value);
});
});
</script>
parent()で親をだどり、formの子供のname=”output”のみに値をセットするようになりました。
その結果、正しくセットされるようになりました。
疑問:parent()を2回つかっているのはなぜ?
修正版では、parentを2回使っていますが、これはなぜなのか?
答えは単純です。
formの下に「div」があり「div」が「input」を囲っているからです。
つまり、コーディングレベルでdivがなければ parent1回でよいということです。
Jqueryのparentはフォームだけでなく、divなどのタグもたどるのです。
ちなみに、サンプルの全ソースがこちらです。
formの下にdivタグがあり、その下にinputタグがある孫構成になっています。
<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>同じパラメータにセット</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$(document).ready(function()
{
$('input[name="input_set"]').click(function()
{
var value = $(this).parent("div").children('input[name=input]').val();
$(this).parent("div").parent("form").children("div").children('input[name="output"]').val(value);
});
});
</script>
<style type="text/css">
section
{
width: 600px;
margin-right: auto;
margin-left: auto;
margin-bottom: 20px;
padding: 20px;
border: 1px solid #CCC;
}
h1
{
margin: 0px;
padding: 0px;
}
input
{
padding: 10px;
}
</style>
</head>
<body>
<section>
<form action="" method="post">
<div class="input">
<h1>入力部分01</h1>
<p>
値を入力して読み込みボタンを押してください。<br>
出力01に入力値が表示されます。
</p>
<input name="input" type="text">
<input name="input_set" type="button" value="値をセット">
</div>
<div class="form">
<h2>出力部分 01</h2>
<input name="output" type="text">
</div>
</form>
</section>
<section>
<form action="" method="post">
<div class="input">
<h1>入力部分02</h1>
<p>
値を入力して読み込みボタンを押してください。<br>
出力01に入力値が表示されます。
</p>
<input name="input" type="text">
<input name="input_set" type="button" value="値をセット">
</div>
<div class="form">
<h2>出力部分 02</h2>
<input name="output" type="text">
</div>
</form>
</section>
</body>
</html>
Jqueryはとても便利ですが、便利ゆえ落とし穴もあったりします。
でも工夫すればより効率的に組むことができるということを、今回学びました。