3

フォームの一部としてユーザーからアイテムに関する情報を収集するために使用されるHTMLの次のブロックがあります。

<div class="clone_block">
  Name: <input type="text" name="items[0][name]" /><br />
  Amount: <input type="text" name="items[0][amount]" /><br />
  <button class="delete">Delete</button>
</div>

この要素のクローンを作成して(ユーザーが別のアイテムを追加したい場合)div.clone_block、DOMの最後のインスタンスの後に配置すると、すべてが正常に機能し、要素を削除することもできます。ただし、同じ名前のテキスト入力のインスタンスが複数あることになります。つまり、POSTリクエストには最後のインスタンスのみが表示されます(前のインスタンスは上書きされます)。私がやりたいのは、最初がitem[0]、2番目がitem[1]などになるように、すべてのアイテムに番号を付け直すことです。

jQueryでこれを行う方法はありますか?この方法で名前を作成すると、PHPでPOSTデータを処理しやすくなるため、可能であれば命名スキームを変更したくありません。

4

3 に答える 3

13

次のように実装して、クローン/削除のたびに要素の名前を変更できます。

function renumber_blocks() {
    $(".clone_block").each(function(index) {
        var prefix = "items[" + index + "]";
        $(this).find("input").each(function() {
           this.name = this.name.replace(/items\[\d+\]/, prefix);   
        });
    });
}

デモ: http: //jsfiddle.net/Wzzf2/1/

于 2012-09-11T13:17:17.630 に答える
6

サーバー側の言語としてPHPを使用している場合は、次のように実行できます。

<div class="clone_block">
  Name: <input type="text" name="items[][name]" /><br />
  Amount: <input type="text" name="items[][amount]" /><br />
  <button class="delete">Delete</button>
</div>

PHPは、データを受信すると、適切なオフセットインデックスの作成を自動的に処理します。

ただし、質問に答えるには、ブロックのクローンを作成したら、その構造をナビゲートし、名前の属性を番号を増やして変更するだけです。または、すべての入力をナビゲートし、追加または削除ボタンが使用されるたびにそれらのインデックスを再作成することをお勧めします...これにより、削除が可能になります。

/// find each row with inputs
$('div.form_row').each(function(rowIndex){
  /// find each input with a name attribute inside each row
  $(this).find('input[name]').each(function(){
    var name;
    name = $(this).attr('name');
    name = name.replace(/\[[0-9]+\]/g, '['+rowIndex+']');
    $(this).attr('name',name);
  });
});

上記は次のマークアップで機能します(そしてテストされています)。インデックスが並べ替えられるのを確認する必要があります。

<div class="form_row"><input name="something[0][abc]"></div>
<div class="form_row"><input name="something[2][abc]"></div>
<div class="form_row"><input name="something[3][abc]"></div>

修正!

PHPを使用してインデックスを生成する際のバグに気づきました...インデックスが配列構造の最後の部分である場合は機能します。

something[abc][]
something[def][]

しかし、あなたが(あなたがそうであるように)使用している場合:

something[][abc]
something[][def]

最終的には次のPHP側になります。

array (
   '0' => array( 'abc' => 'value' ),
   '1' => array( 'def' => 'value' ),
)

それよりも:

array (
   '0' => array( 
     'abc' => 'value',
     'def' => 'value',
   ),
);

おそらくどちらがあなたが望むものです。したがって、あなたの例では、私が言及したPHPルートを無視し、代わりにjQueryスニペットを使用します。ただし、行ごとに入力が1つしかない場合でも、PHPソリューションは便利です...

于 2012-09-11T13:06:59.087 に答える
3

コピー中にインデックスを使用して何か他のことをしたい場合は、もう少し複雑になります。

var name = $('input').attr('name'),
    newId = parseInt(name.match(/\d+/)[1])++;

// clone the input and use newId for something else

$('input.new').attr('name', name.replace(/\d+/, newId));
于 2012-09-11T13:14:57.283 に答える