首页 > 解决方案 > 使用 JavaScript 克隆 IList 中的项目

问题描述

我有一个看起来像这样的视图模型

 public class ItemViewModel
    {
        [Required]
        public int Id { get; set; }
        [Required]
        public int JobId { get; set; }
        public string ItemId { get; set; }
        public string ItemName { get; set; }
        public IList<ItemPartViewModel> Parts { get; set; }
    }

如您所见,它包含一个 IList of Parts,其结构如下

 public class ItemPartViewModel
    {
        [Required]
        public int ID { get; set; }
        public int ItemID { get; set; }
        public string PartID { get; set; }
        public string PartName { get; set; }
        public float QtyInItem { get; set; }
        public float Qty { get; set; }
        public bool MoveAll { get; set; }
        // This is the additional property to contain what user picks, the action types are harvest/transfer/dispose
        public PartActionType SelectedActionType { get; set; }
    }

显示表格时,已选中该行中的 moveAll 选项,但如果未选中,它将克隆该行。这是为了如果用户想要做这样的事情,例如//如果项目中有 4 个部分并且选择了 moveall 选项,它将对所有 4 个部分执行选定的操作。但如果不是,并且用户决定转移 2 并处置 2,我需要跟踪它。这是克隆行的 JavaScript

  $(document).ready(function () {
            $('.tr_clonePart input.part-class').change(function () {

                let Id = $(this).attr('id');
                let partId = $(this).attr('data-partId');
                //getting closest tr
                var selector = $(this).closest('.tr_clonePart');
                if ($(this).prop("checked") == true){
                    // remove cloned row
                    $('#' + Id + 'clone').remove();

                    selector.find(".AllTxt").show();
                    selector.find(".editQty").hide();
                }
                else {
                    var $tr = $(this).closest('.tr_clonePart');
                    var $clone = $tr.clone();
                    $clone.find('td');
                    $tr.after($clone);
                    $($clone).find(".part-class").hide();
                    //var qtyInItem = $('input[name=Parts['+partId+"].QtyInItem").val()


                    $clone.find('input[type="radio"]').attr("name", (i, n) => n + 'clone');
                    $clone.attr('id', (Id) + "clone");
                    var clonedID = Id + "clone";
                    $($clone).append($("<td class= 'addRow' ><a href=\"javascript:add('" + clonedID + "')\">add row</a></td>"));
                    selector.find(".AllTxt").hide();
                    selector.find(".editQty").show();
                    
                }

            });

这是我的行的设置

<tr class="tr_clonePart">
   <td>
       @part.PartIDLink
   </td>
   <td>
       @Html.DisplayFor(x => x.Parts[i].PartName)
       @Html.HiddenFor(x => x.Parts[i].PartName)
   </td>
   <td style="font-weight:bold">
       <span class="qtyInItem">
           @Html.DisplayFor(x => x.Parts[i].QtyInItem)
           @Html.HiddenFor(x => x.Parts[i].QtyInItem)
       </span>
   </td>
   <td>                            
       @Html.CheckBoxFor(x => x.Parts[i].MoveAll, new {  @class="part-class", data_partId = part.ID })
   </td>                              
   <td>
       <div class="AllTxt">
           @Html.DisplayFor(x => x.Parts[i].QtyInItem)
       </div>
       <div class="editQty">
           @Html.EditorFor(x => x.Parts[i].Qty)
       </div>
   </td>                            
       @foreach (var actionType in partActionTypes)
           {
               <td>
                   @Html.RadioButtonFor(x => x.Parts[i].SelectedActionType, actionType, new { name = "partRadio" })
               </td>
           }
</tr>

这是我的观点的图片,以帮助更清楚地了解我的情况 看法

在那种情况下,它只会跟踪 0.5 的转移,但我希望列表也有正在收获的 0.5 的记录

我怎样才能使它本质上也“克隆”零件列表中的行?

标签: javascriptc#ajaxlistrazor

解决方案


您可以为该cloned行提供类,这将其与原始行和克隆行区分开来。在下面的代码中,我part_id用来区分它们。此外,我已经给class所有输入以轻松检索其值。现在,要发送我创建的这些值(克隆的和原始的),JSON Array因为这里所有输入的值都是相同的,quantity并且actiontype会更改以保存我创建的这些值arrays。最后,您可以将生成的JSON Arrayusing发送ajax到您的后端。

演示代码

$('.tr_clonePart input.part-class').change(function() {
  let Id = $(this).attr('id');
  let partId = $(this).attr('data-partId');
  //getting closest tr
  var selector = $(this).closest('.tr_clonePart');
  //get original radio 
  var radios_old = selector.find("input[type='radio']:checked");
  if ($(this).prop("checked") == true) {
    // remove cloned row
    $('.tr_clonePart_' + partId).remove();
    selector.find(".AllTxt").show();
    selector.find(".editQty").hide();
  } else {

    var $tr = $(this).closest('.tr_clonePart');
    var $clone = $tr.clone();
    //remove class `tr_clonePart` from cloned tr add new class tr_clonePart_parid 
    $clone.removeClass('tr_clonePart').addClass('tr_clonePart_' + partId)
    $tr.after($clone);
    $($clone).find(".part-class").hide();
    //give unique name to radios
    $clone.find('input[type="radio"]').attr("name", 'clone' + partId);

    $clone.attr('id', (Id) + "clone");
    var clonedID = 'tr_clonePart_' + partId;
    $($clone).append($("<td class= 'addRow' ><a href=\"javascript:add('" + clonedID + "')\">add row</a></td>"));
    selector.find(".AllTxt").hide();
    selector.find(".editQty").show();
    //checking if the radio value was check before
    if (radios_old.length == 1) {
      //apply checked
      radios_old.prop('checked', true)
    }

  }

});

//on clicked of button
$("button").click(function() {
  var array = []; //for creating json array
  //looping through trs with class tr_clonePart
  $(".tr_clonePart").each(function() {
    //for storing qtys and radios of cloned and original
    var qtys = []
    var radios_c = [];
    //get infos for various fields
    var p_id = $(this).find("td > a").attr('p-id');
    var mfg = $(this).find("input.part_mfg").val();
    var part_name = $(this).find("input.part_name").val();
    var qty_in_used = $(this).find("input.qty_in_item").val();
    var item = {};
    //add values in json objects
    item["p_id"] = p_id
    item["mfg"] = mfg
    item["part_name"] = part_name
    item["qty_in_used"] = qty_in_used
    //chcking if part-class is checked or not 
    if ($(this).find("input[type='checkbox'].part-class").is(':checked')) {

      var move_all = $(this).find("input[type='checkbox'].part-class").val();
      item["move_all"] = move_all
      var radios = $(this).find("input[type='radio'].radios:checked").val();
      radios_c.push(radios) //adding value of radios in array
      item['radios_c'] = radios_c
      var qty = $(this).find("input.qty").val();
      qtys.push(qty) //adding value of qty in array
      item["qty"] = qtys
    } else {
      var qty = $(this).find("input.qty").val();
      qtys.push(qty)
      var radios = $(this).find("input[type='radio'].radios:checked").val();
      radios_c.push(radios)
      //looping through cloned trs 
      $(".tr_clonePart_" + p_id).each(function() {
        item["move_all"] = "false"
        var radios_clones = $(this).find("input[type='radio'].radios:checked").val();
        radios_c.push(radios_clones)
        var qty_clones = $(this).find("input.qty").val();
        qtys.push(qty_clones)
      });
      item['radios_c'] = radios_c
      item['qtys'] = qtys
    }
    //getting other values
    var onhand = $(this).find("input.onhand").val();
    var onwork = $(this).find("input.onwork").val();
    var commited = $(this).find("input.committed").val();
    var fstk = $(this).find("input.fstk").val();
    item["onhand"] = onhand
    item["onwork"] = onwork
    item["commited"] = commited
    item["fstk"] = fstk
    //push json object in array
    array.push(item)

  })
  console.log(array)
  //console.log(JSON.stringify(array))
  //ajax call to save data to backend


})
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

<table class="table table-bordered">
  <tr>
    <th>
      IGT Part ID
    </th>
    <th>
      MFG ID
    </th>
    <th>
      Part Name
    </th>
    <th>
      Qty used in Item
    </th>
    <th>
      Move All
    </th>
    <th>
      Qty
    </th>
    <th>
      On-hand Qty
    </th>
    <th>
      On Work Order
    </th>
    <th>
      Committed
    </th>
    <th>
      F. Stock
    </th>
    <th style="color:blue">
      Transfer
    </th>
    <th style="color:forestgreen">
      Harvest
    </th>
    <th style="color:red">
      Dispose
    </th>
    <th class="noprint"></th>
  </tr>
  <tbody>
    <input data-val="true" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="Parts_0__ID" name="Parts[0].ID" type="hidden" value="346" /><input id="Parts_0__PartID" name="Parts[0].PartID" type="hidden"
      value="600601" /><input data-val="true" data-val-number="The field ItemID must be a number." data-val-required="The ItemID field is required." id="Parts_0__ItemID" name="Parts[0].ItemID" type="hidden" value="117" />
    <tr class="tr_clonePart">

      <td>
        <a p-id=346 style='color:#FF00FF;' href='#'>600601</a>
      </td>
      <td>
        S-16706, Uline
        <!--added class to all inputs-->
        <input id="Parts_0__MFGNumber" class="part_mfg" name="Parts[0].MFGNumber" type="hidden" value="S-16706, Uline" />
      </td>
      <td>
        Supply Packing
        <input id="Parts_0__PartName" class="part_name" name="Parts[0].PartName" type="hidden" value="Supply  Packing " />
      </td>
      <td style="font-weight:bold">
        <span class="qtyInItem">
1
<input data-val="true" data-val-number="The field QtyInItem must be a number." class="qty_in_item"  data-val-required="The QtyInItem field is required." id="Parts_0__QtyInItem" name="Parts[0].QtyInItem" type="hidden" value="1" />
</span>

      </td>
      <td>
        <input checked="checked" class="part-class" data-partId="346" data-val="true" data-val-required="The MoveAll field is required." id="Parts_0__MoveAll" name="Parts[0].MoveAll" type="checkbox" value="true" /><input name="Parts[0].MoveAll" type="hidden"
          value="false" />
      </td>

      <td>
        <div class="AllTxt">
          1
        </div>
        <div class="editQty">
          <input class="text-box single-line qty" data-val="true" data-val-number="The field Qty must be a number." data-val-required="The Qty field is required." id="Parts_0__Qty" name="Parts[0].Qty" type="text" value="0" />
        </div>
      </td>
      <td>
        <span class="onHand">
27
<input data-val="true" class="onhand" data-val-number="The field OnHand must be a number." data-val-required="The OnHand field is required." id="Parts_0__OnHand" name="Parts[0].OnHand" type="hidden" value="27" />
</span>
      </td>
      <td>
        <span class="onWorkOrder">
0
<input data-val="true"  class="onwork" data-val-number="The field OnWorkOrder must be a number." data-val-required="The OnWorkOrder field is required." id="Parts_0__OnWorkOrder" name="Parts[0].OnWorkOrder" type="hidden" value="0" />
</span>
      </td>
      <td>
        <span class="committed">
93
<input data-val="true"   class="committed" data-val-number="The field Committed must be a number." data-val-required="The Committed field is required." id="Parts_0__Committed" name="Parts[0].Committed" type="hidden" value="93" />
</span>

        <td>
          <span class="fstk">
-66
<input data-val="true"  class="fstk" data-val-number="The field FSTK must be a number." data-val-required="The FSTK field is required." id="Parts_0__FSTK" name="Parts[0].FSTK" type="hidden" value="-66" />
</span>
        </td>


        <td>
          <input checked class="radios" data-val="true" data-val-required="The SelectedActionType field is required." id="Parts_0__SelectedActionType" name="Parts[0].SelectedActionType" type="radio" value="Transfer" />
        </td>
        <td>
          <input id="Parts_0__SelectedActionType" class="radios" name="Parts[0].SelectedActionType" type="radio" value="Harvest" />
        </td>
        <td>
          <input id="Parts_0__SelectedActionType" class="radios" name="Parts[0].SelectedActionType" type="radio" value="Dispose" />
        </td>
    </tr>
    <tr class="tr_clonePart">

      <td>
        <a p-id=347 style='color:#FF00FF;' href='#'>600602</a>
      </td>
      <td>
        S-16706, Ulineg
        <input id="Parts_0__MFGNumber" class="part_mfg" name="Parts[0].MFGNumber" type="hidden" value="S-16706, Ulineg" />
      </td>
      <td>
        Packing Carton
        <input id="Parts_0__PartName" class="part_name" name="Parts[0].PartName" type="hidden" value=" Packing Carton" />
      </td>
      <td style="font-weight:bold">
        <span class="qtyInItem">
1
<input data-val="true" data-val-number="The field QtyInItem must be a number." class="qty_in_item"  data-val-required="The QtyInItem field is required." id="Parts_0__QtyInItem" name="Parts[0].QtyInItem" type="hidden" value="1" />
</span>

      </td>
      <td>
        <input checked class="part-class" data-partId="347" data-val="true" data-val-required="The MoveAll field is required." id="Parts_0__MoveAll" name="Parts[0].MoveAll" type="checkbox" value="true" /><input name="Parts[0].MoveAll" type="hidden" value="false"
        />
      </td>

      <td>
        <div class="AllTxt">
          1
        </div>
        <div class="editQty">
          <input class="text-box single-line qty" data-val="true" data-val-number="The field Qty must be a number." data-val-required="The Qty field is required." id="Parts_0__Qty" name="Parts[1].Qty" type="text" value="0" />
        </div>
      </td>
      <td>
        <span class="onHand">
2
<input data-val="true" class="onhand" data-val-number="The field OnHand must be a number." data-val-required="The OnHand field is required." id="Parts_0__OnHand" name="Parts[1].OnHand" type="hidden" value="2" />
</span>
      </td>
      <td>
        <span class="onWorkOrder">
0
<input data-val="true"  class="onwork" data-val-number="The field OnWorkOrder must be a number." data-val-required="The OnWorkOrder field is required." id="Parts_0__OnWorkOrder" name="Parts[1].OnWorkOrder" type="hidden" value="0" />
</span>
      </td>
      <td>
        <span class="committed">
9
<input data-val="true"   class="committed" data-val-number="The field Committed must be a number." data-val-required="The Committed field is required." id="Parts_0__Committed" name="Parts[1].Committed" type="hidden" value="9" />
</span>

        <td>
          <span class="fstk">
-6
<input data-val="true"  class="fstk" data-val-number="The field FSTK must be a number." data-val-required="The FSTK field is required." id="Parts_0__FSTK" name="Parts[1].FSTK" type="hidden" value="-6" />
</span>
        </td>


        <td>
          <input class="radios" data-val="true" data-val-required="The SelectedActionType field is required." id="Parts_0__SelectedActionType" name="Parts[1].SelectedActionType" type="radio" value="Transfer" />
        </td>
        <td>
          <input checked="checked" id="Parts_0__SelectedActionType" class="radios" name="Parts[1].SelectedActionType" type="radio" value="Harvest" />
        </td>
        <td>
          <input id="Parts_0__SelectedActionType" class="radios" name="Parts[1].SelectedActionType" type="radio" value="Dispose" />
        </td>
    </tr>
</table>

<button class="btn btn-success" style="margin:10px">Click Me ! </button>

在后端,您只需将数据类型更改Qty为数组并为数组创建新字段actionType以保存输入和无线电的值。


推荐阅读