JS/JQuery : 在生成新字段的同时继续表单数组的索引

Posted

技术标签:

【中文标题】JS/JQuery : 在生成新字段的同时继续表单数组的索引【英文标题】:JS/JQuery : continue with the index of array of the form while generating new fields 【发布时间】:2017-12-24 01:25:00 【问题描述】:

我有一个使用 php 和 foreach 循环动态生成的表单。

此表单的输入字段依次返回 3-D 数组中的数据,这样可以轻松回溯提交这些字段的位置以及如何存储它们。所以这是表格:

<?php

$i = 0;

foreach ($shop->fetch()->showResults() as $sr)
    $j = 0;
    if($i == 0)
        echo '<div id="ser'.$sr->id.'" location = "'.$sr->id.'" class="tab-pane fade active in">';
        $i++;
     else
        echo '<div id="ser'.$sr->id.'" location = "'.$sr->id.'" class="tab-pane fade">';
        $i++;
    

    $ser = new Service(Input::get('cd'));
    $ser->fetchPriceInShop($sr->id, $ser->fetchData()->id);
    foreach ($ser->fetchData() as $price)
        echo '<input type="text" value="'.$price->duration.'" name="price['.$sr->id.']['.$j.'][duration]" placeholder="duration (in Minutes)">
              <input type="text" value="'.$price->price.'" name="price['.$sr->id.']['.$j.'][price]" placeholder="Price ($ 100)">
              <br>';
        $j++;
    
    echo '
    <button style="float: right;" class="addPrice" type="button">+</button>
    </div>';


?>

所以生成的表单是这样的:

<input type="text" value="10.00" name="price[1][0][price]" placeholder="Price ($ 100)">
<br><input type="text" value="20" name="price[1][1][duration]" placeholder="duration (in Minutes)">
<input type="text" value="20.00" name="price[1][1][price]" placeholder="Price ($ 100)">
<br><input type="text" value="30" name="price[1][2][duration]" placeholder="duration (in Minutes)">
<input type="text" value="30.00" name="price[1][2][price]" placeholder="Price ($ 100)">
<br>

现在,我正在尝试使此表单更灵活,我可以在其中添加更多字段并使用它们提交值。为此使用以下js:

$(".addPrice").on("click", function()
    var location = $(this).parent().attr('location');

    var element = '<input type="text" placeholder="duration (minutes)" name="prices['+location+'][index][duration]">';
    element += '<input type="text" placeholder="price (aud)" name="prices['+location+'][index][price]"><br>';
    $(this).parent().append(element);
);

我以某种方式设法获取第一个索引(位置),最后一个索引是静态的,但我不知道如何找到生成的数组的第二个索引。请帮我找出解决方案。

PS:我是堆栈溢出的菜鸟,所以请不要苛刻。我正在学习使用这个平台。

【问题讨论】:

您不应该尝试为每个输入字段指定一个唯一的名称。相反,给它们所有相同的数组名称,如name="price[]"name="duration[]"。之后,您可以简单地在 PHP 中遍历这些数组来检索每个值。 对于 DRYness,如果您在 if/else 块之后编写两个 i++ 语句,则可以将其合并为一个语句。这样,无论$i=0 是否都会保证递增。 也许重新配置您的多维数组结构以使用最深元素的索引。换句话说,声明为price[$sr-&gt;id]['price'][],那么您不必为$j 的递增而烦恼。然后在您的 jquery 中,您可以只使用:name="prices['+location+'][price][]",而无需搜索要使用的正确 index。这与icecub建议的原则基本相同。 我刚刚意识到输入名称值中有一个错字——priceprices。只是需要在每个人的代码中修复。 【参考方案1】:

我建议重新构建您的多维数组以避免不必要的计数/递增。

生成php代码的表单:

$i=0;
foreach($shop->fetch()->showResults() as $sr)
    echo "<div id=\"ser$sr->id\" location=\"$sr->id\" class=\"tab-pane fade",(!$i++?" active in":""),"\">";
        $ser=new Service(Input::get('cd'));
        $ser->fetchPriceInShop($sr->id, $ser->fetchData()->id);
        foreach($ser->fetchData() as $price)
            echo "<input type=\"text\" value=\"$price->duration\" name=\"price[$sr->id][duration][]\" placeholder=\"duration (in Minutes)\">
              <input type=\"text\" value=\"$price->price\" name=\"price[$sr->id][price][]\" placeholder=\"Price ($ 100)\">
              <br>";
        
        echo "<button style=\"float:right;\" class=\"addPrice\" type=\"button\">+</button>";
    echo "</div>";

*注意$i++ 条件首先检查它是否为零,然后递增。这可以保持您的预期用途。 Demo of this technique

jquery 代码:

$(".addPrice").on("click", function()
    var location = $(this).parent().attr('location');    
    var element = '<input type="text" placeholder="duration (minutes)" name="price['+location+'][duration][]">';
    element += '<input type="text" placeholder="price (aud)" name="price['+location+'][price][]"><br>';
    $(this).parent().append(element);
);

我可能还想推荐使用data-location 而不是location 作为属性名称。

【讨论】:

我也想到了这一点,但我认为,也许是错误的,索引是有原因的,例如需要维护排序顺序。 @AlexanderHiggins 这种方法会如何破坏排序顺序?我忽略了什么吗?我认为唯一能做的就是强制 OP 在提交后重新编码数据处理——但不会以一种太麻烦的方式。 一般来说,如果数组被绑定到模型或序列化,数据结构已经改变。通俗的说,以xml为例,原来的可能序列化为 但通过改变它可能的结构。 。这可能看起来过于宽泛,但并不少见,尤其是在 JSON 盛行的情况下。 考虑原来的结构:var price=[[],[]];价格[0][0]=时长:“价值”,价格:“价值”;价格[0][1]=时长:“价值”,价格:“价值”; price[0][2]=duration:"value",price:"value" price[1][0]=duration:"value",price:"value";价格[1][1]=时长:“价值”,价格:“价值”;价格[1][2]=时长:“价值”,价格:“价值”; console.log(JSON.stringify(price)); [["duration":"value","price":"value","duration":"value","price":"value","duration":"value","price" :"value"],["duration":"value","price":"value","duration":"value","price":"value","duration":"价值","价格":"价值"]] 这是你的:var price=[,];价格[0]["持续时间"]=["价值","价值","价值"];价格[0]["价格"]=["价值","价值","价值"];价格[1]["持续时间"]=["价值","价值","价值"];价格[1]["价格"]=["价值","价值","价值"]; console.log(JSON.stringify(price)); ["duration":["value","value","value"],"price":["value","value","value"],"duration":["value","价值","价值"],"价格":["价值","价值","价值"]]【参考方案2】:

您可以向价格元素添加一个类,并使用该类计算元素。

 var idx = parent.find('.price').length;

function parsePrice(el) 
  var parent = $(el).parent();
  var location = parent.attr("location");

  var idx = parent.find('.price').length;
  var element = '<input type="text" placeholder="duration (minutes)" name="price[' + location + '][' + idx + '][duration]">';
  element += '<input type="text" placeholder="price (aud)" name="price[' + location + ']['+idx+'][price]"><br>';
  
  $(element).insertBefore(el);


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="1" location="1" class="tab-pane fade active in">
  <input type="text" value="10" name="price[1][0][duration]" placeholder="duration (in Minutes)">
  <input class="price" type="text" value="10.00" name="price[1][0][price]" placeholder="Price ($ 100)">
  <br><input type="text" value="20" name="price[1][1][duration]" placeholder="duration (in Minutes)">
  <input class="price" type="text" value="20.00" name="price[1][1][price]" placeholder="Price ($ 100)">
  <br><input type="text" value="30" name="price[1][2][duration]" placeholder="duration (in Minutes)">
  <input class="price" type="text" value="30.00" name="price[1][2][price]" placeholder="Price ($ 100)">
  <br>
  <input type="button" onclick="parsePrice(this);" value="go" />
</div>

或者,您可以将元素分组到父容器中,例如 PHP 循环中的 div

 foreach ($ser->fetchData() as $price)
    echo '<div class="pricediv price-'.$sr->id.'"><input type="text" value="'.$price->duration.'" name="price['.$sr->id.']['.$j.'][duration]" placeholder="duration (in Minutes)">
          <input type="text" value="'.$price->price.'" name="price['.$sr->id.']['.$j.'][price]" placeholder="Price ($ 100)">
          </div>';
    $j++;

然后选择这些元素的计数:

function parsePrice(el) 
  var parent = $(el).parent();
  var location = parent.attr("location");
  var idx = parent.find('div').length;
  var element = '<input type="text" placeholder="duration (minutes)" name="price[' + location + '][' + idx + '][duration]">';
  element += '<input type="text" placeholder="price (aud)" name="price[' + location + '][' + idx + '][price]"><br>';
  $(element).insertBefore(el);


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="1" location="1" class="tab-pane fade active in">
  <div class="pricediv price-1"><input type="text" value="10" name="price[1][0][duration]" placeholder="duration (in Minutes)">
    <input class="price" type="text" value="10.00" name="price[1][0][price]" placeholder="Price ($ 100)">
  </div>
  <div class="pricediv price-2"><input type="text" value="20" name="price[1][1][duration]" placeholder="duration (in Minutes)">
    <input class="price" type="text" value="20.00" name="price[1][1][price]" placeholder="Price ($ 100)">
  </div>
  <div class="pricediv price-3"><input type="text" value="30" name="price[1][2][duration]" placeholder="duration (in Minutes)">
    <input class="price" type="text" value="30.00" name="price[1][2][price]" placeholder="Price ($ 100)">
    <br>
    <input type="button" onclick="parsePrice(this);" value="go" />
  </div>

【讨论】:

刚刚在 OP 的代码中发现拼写错误,检查输入的名称值 priceprices。我刚刚将我的更改为price(任意)。 我会跟随你的。 +1 提醒。【参考方案3】:

您可以使用按标签名称获取元素来查找索引。

$(".addPrice").on("click", function()
    var location = $(this).parent().attr('location');
    var index=$(this).parent().getElementsByTagName("input").length/2;
    var element = '<input type="text" placeholder="duration (minutes)" name="prices['+location+']['+index+'][duration]">';
    element += '<input type="text" placeholder="price (aud)" name="prices['+location+']['+index+'][price]"><br>';
    $(this).parent().append(element);
);

【讨论】:

虽然这是一个解决方案,但请考虑@icecub 为组使用相同名称属性的建议,这是正确的方法。如果您满意,请接受我的回答。

以上是关于JS/JQuery : 在生成新字段的同时继续表单数组的索引的主要内容,如果未能解决你的问题,请参考以下文章

在表单字段中输入文本,在提交时生成多个 URL 并在新选项卡中打开链接

将表单名称发送到 JS/jQuery 和序列化

使用JQuery实现验证提交表单信息;且提示信息在指定时间自动隐藏

js总结(11)一个页面同时提交多个form表单的实施

创建的新文本字段与先前文本字段的值一起出现在颤动中

在 Shopify JSON 模板中添加自定义表单字段