首页 > 解决方案 > 在 AJAX 表单提交中使用 jquery 数据选择器识别哪个类发出请求

问题描述

我有一系列组,每个组都包含项目列表。我在数量字段中添加了递减/递增按钮,并希望它可以通过 AJAX 工作。

输入字段之一的示例 html 是

<div class="ContentCell list_product_qty_wrapper nbr nbt">
  <input type="text" name="cartlist_quantity" value="1" size="4" class="cart_input_1881" />
  <input type="hidden" name="products_id" value="1881" />
  <input type="hidden" name="cartlist_group_id" value="1" />
</div>

将递增/递减按钮添加到输入字段并启动 AJAX 调用的完整脚本是

// Add Increment/Decrement buttons
function add_quantity_buttons(element, vertical) {
  quantity_input = jQuery(element);
  quantity_input.attr('min', '0').attr('inputmode', 'numeric').attr('pattern', '[0-9]*').addClass('inc_dec_quantity_field').wrap('<div class="quantity_field_wrapper clearfix"></div>');

  if (jQuery('.device-xs').is(':visible')) {
    quantity_input.attr('type', 'number');
  } else {
    quantity_input.attr('type', 'text');
  }

  quantity_input.before('<a href="#decrease_quantity" class="quantity_dec_button">-</a>').after('<a href = "#increase_quantity" class = "quantity_inc_button" > + </a>');
}

// Handle quantity buttons
// Increment/Decrement button functionality
function increment_decrement_quantity(element, value) {
  $(document.body).on('click', element, function(e) {
    e.preventDefault();
    quantity = $(this).parent().find(('input'));
    quantity_value = parseInt(quantity.val(), 10);
    quantity_multiple = undefined;

    if (quantity.data('multiple') !== undefined && (quantity.data('multiple') > 0 || quantity.data('multiple') < 0)) {
      quantity_multiple = parseInt(quantity.data('multiple'), 10);
      if (value < 0) {
        quantity_multiple = quantity_multiple * -1;
      }
    }

    if (quantity_multiple !== undefined && (quantity_multiple > 0 || quantity_multiple < 0)) {
      quantity_value = Math.floor(quantity_value / quantity_multiple) * quantity_multiple;
      value = quantity_multiple;
    } else {
      value = parseInt(value, 10);
    }

    // Validate quantity and increment/decrement value
    if (value > 0 || value < 0 && quantity_value > 0) {
      quantity.val(quantity_value + value).trigger('change');
    }
  });
}

// Remove number type and add quantity change buttons
add_quantity_buttons('#listContentsDisplay input[name^="cartlist_quantity"]', true);

// Decrement button
increment_decrement_quantity('.quantity_dec_button', -1);

// Increment button
increment_decrement_quantity('.quantity_inc_button', +1);

// Quantity input validation
var ajax_called = false;
$(document.body).on('propertychange change click keyup input paste blur', '.inc_dec_quantity_field', function(e) {
  character_code = !e.charCode ? e.which : e.charCode;
  quantity_value = $(this).val();
  leading_zero_plus_regexp = /^(0[0-9]|\+[\+,0-9]).*$/;

  // When input goes out of focus validate quantity value
  if (e.type == 'blur' && (quantity_value == '' || isNaN(quantity_value / 1) == true || isNaN(quantity_value / 1) == false && quantity_value <= 0)) {
    $(this).val('0');
  } else {
    // Check for numeric value and allow backspace, delete, left and right arrows
    if ((isNaN(quantity_value / 1) == false && quantity_value > 0) || (character_code != undefined && (character_code == 39 || character_code == 37 || character_code == 8 || character_code == 46))) {
      // Correct value
      // Make sure the quantity is integer
      if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
        $(this).val(parseInt(quantity_value, 10));
      }
    } else if (character_code != undefined) {
      // Incorrect value
      $(this).val('0');
    } else if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
      // Make sure the quantity is integer
      $(this).val(parseInt(quantity_value, 10));
    }
  }

  // AJAX update quantity
  //if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper') && !ajax_called) {
  //if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper[data-groupid="' + jQuery(this).data("groupid") + '"]') && !ajax_called) {
 // if (e.type != 'click' && $(e.target).parent().parent().data('groupid') == jQuery(this).data("groupid") && !ajax_called) { changed to this after suggestion from Ivan (SO)
  if (e.type != 'click' && $(e.target).data('groupid') == jQuery(this).data("groupid") && !ajax_called) { // Ivan (SO) suggestion didn't give an 'OK' in console log. Removing .parent().parent(), it does give an ok, but still only submits the last group to AJAX update 
    console.log('OK');
    call_delay(function() {
      var form = $('form[name="cartlist"]');
      ajax_called = true;
      $.ajax({
        type: form.attr('method'),
        url: form.attr('action'),
        data: form.serialize()
      }).success(function(data) {

      if ($('#cartlistDefault').length && $(data).find('#cartlistDefault').length) {
        $('#cartlistDefault').replaceWith($(data).find('#cartlistDefault'));

          // Remove number type and add quantity change buttons
          add_quantity_buttons('#listContentsDisplay input[name^="cartlist_quantity"]', true);
          // Replace classes missing after AJAX callback
          $('select').addClass('select_caret_icon form-control');
          if ($('input[type="submit"].cssButton').length > 0) {
            $('input[type="submit"].cssButton').attr("data-btn", "btn btn-md");
          }
        }

        ajax_called = false;
      }).fail(function(data) {
        ajax_called = false;
      });
    }, 300);
  }
});    

我的问题是增量仅适用于while循环中生成的最后一个组。

根据我昨天提出的一个问题(多个复选框来触发 js 脚本),我在识别请求来自哪个组时遇到了类似的问题,我在这里尝试了相同的方法,

更换

<div class="ContentCell list_product_qty_wrapper nbr nbt">

<div class="ContentCell list_product_qty_wrapper nbr nbt" data-groupid="1">

在脚本中,替换

if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper') && !ajax_called) {

if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper[data-groupid="' + jQuery(this).data("groupid") + '"]') && !ajax_called) {

但是,在这样做之后,没有一个增量按钮会触发 AJAX 进程。

这个小提琴https://jsfiddle.net/8h4gzmu3/显示了输入字段和增量/减量的样子,并且按钮在单击时确实会更新数量,一旦AJAX调用完成,第一个和第二个输入不是更新。只有最后一个是。

显然我还没有完全掌握使用数据选择器的概念。

我哪里做错了?

标签: jquery

解决方案


因为您正在使用 hasClass 来查看类而不是属性,而在 html 中您正在添加 data-groupid 作为属性

如果父数据组ID相同,您可以尝试这个应该工作

if (e.type != 'click' && $(e.target).parent().parent().data('groupid') == jQuery(this).data("groupid") && !ajax_called) {

更新

您可以按照此逻辑来执行此操作,为按钮和当前输入添加相同的 groupid,然后在 if statment 中将它们相互匹配。

这是匹配当前输入的示例,如果您更改输入 groupid 与按钮 groupid 不同,如果 statment 将为 FALSE 并且您不会获得控制台日志

// Add Increment/Decrement buttons
function add_quantity_buttons(element, vertical) {
  quantity_input = jQuery(element);
  quantity_input.attr('min', '0').attr('inputmode', 'numeric').attr('pattern', '[0-9]*').addClass('inc_dec_quantity_field').wrap('<div class="quantity_field_wrapper clearfix"></div>');

  if (jQuery('.device-xs').is(':visible')) {
    quantity_input.attr('type', 'number');
  } else {
    quantity_input.attr('type', 'text');
  }

  quantity_input.before('<a href="#decrease_quantity" data-group-id="1" class="quantity_dec_button">-</a>').after('<a href = "#increase_quantity" data-groupid="1" class = "quantity_inc_button" > + </a>');
}

// Handle quantity buttons
// Increment/Decrement button functionality
function increment_decrement_quantity(element, value) {
  $(document.body).on('click', element, function(e) {
    e.preventDefault();
    quantity = $(this).parent().find(('input'));
    quantity_value = parseInt(quantity.val(), 10);
    quantity_multiple = undefined;

    if (quantity.data('multiple') !== undefined && (quantity.data('multiple') > 0 || quantity.data('multiple') < 0)) {
      quantity_multiple = parseInt(quantity.data('multiple'), 10);
      if (value < 0) {
        quantity_multiple = quantity_multiple * -1;
      }
    }

    if (quantity_multiple !== undefined && (quantity_multiple > 0 || quantity_multiple < 0)) {
      quantity_value = Math.floor(quantity_value / quantity_multiple) * quantity_multiple;
      value = quantity_multiple;
    } else {
      value = parseInt(value, 10);
    }

    // Validate quantity and increment/decrement value
    if (value > 0 || value < 0 && quantity_value > 0) {
      quantity.val(quantity_value + value).trigger('change');
    }
  });
}

// Remove number type and add quantity change buttons
add_quantity_buttons('.ContentCell input[name^="cartlist_quantity"]', true);

// Decrement button
increment_decrement_quantity('.quantity_dec_button', -1);

// Increment button
increment_decrement_quantity('.quantity_inc_button', +1);

// Quantity input validation
var ajax_called = false;
$(document.body).on('propertychange change click keyup input paste blur', '.inc_dec_quantity_field', function(e) {
  character_code = !e.charCode ? e.which : e.charCode;
  quantity_value = $(this).val();
  leading_zero_plus_regexp = /^(0[0-9]|\+[\+,0-9]).*$/;

  // When input goes out of focus validate quantity value
  if (e.type == 'blur' && (quantity_value == '' || isNaN(quantity_value / 1) == true || isNaN(quantity_value / 1) == false && quantity_value <= 0)) {
    $(this).val('0');
  } else {
    // Check for numeric value and allow backspace, delete, left and right arrows
    if ((isNaN(quantity_value / 1) == false && quantity_value > 0) || (character_code != undefined && (character_code == 39 || character_code == 37 || character_code == 8 || character_code == 46))) {
      // Correct value
      // Make sure the quantity is integer
      if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
        $(this).val(parseInt(quantity_value, 10));
      }
    } else if (character_code != undefined) {
      // Incorrect value
      $(this).val('0');
    } else if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
      // Make sure the quantity is integer
      $(this).val(parseInt(quantity_value, 10));
    }
  }

  // AJAX update quantity
  //if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper') && !ajax_called) {
  //if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper[data-groupid="' + jQuery(this).data("groupid") + '"]') && !ajax_called) {
 // if (e.type != 'click' && $(e.target).parent().parent().data('groupid') == jQuery(this).data("groupid") && !ajax_called) { changed to this after suggestion from Ivan (SO)
  if (e.type != 'click' && $('.quantity_inc_button').data("groupid") == $(e.target).data('groupid') && !ajax_called) { // Ivan (SO) suggestion didn't give an 'OK' in console log. Removing .parent().parent(), it does give an ok, but still only submits the last group to AJAX update 
    console.log('input groupid: ' + $(e.target).data('groupid'));
     console.log('button groupid: ' + $('.quantity_inc_button').data("groupid"));
     console.log('OK')
   // call_delay(function() {
   //   var form = $('form[name="cartlist"]');
   //   ajax_called = true;
   //   $.ajax({
   //     type: form.attr('method'),
   //     url: form.attr('action'),
   //     data: form.serialize()
   //   }).success(function(data) {

   //   if ($('#cartlistDefault').length && $(data).find('#cartlistDefault').length) {
    //    $('#cartlistDefault').replaceWith($(data).find('#cartlistDefault'));

          // Remove number type and add quantity change buttons
    //      add_quantity_buttons('#listContentsDisplay input[name^="cartlist_quantity"]', true);
          // Replace classes missing after AJAX callback
    //      $('select').addClass('select_caret_icon form-control');
    //      if ($('input[type="submit"].cssButton').length > 0) {
    //        $('input[type="submit"].cssButton').attr("data-btn", "btn btn-md");
    //      }
    //    }

    //    ajax_called = false;
   //   }).fail(function(data) {
   //     ajax_called = false;
   //   });
   // }, 300);
  }
});    
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="ContentCell list_product_qty_wrapper nbr nbt">
  <input type="text" name="cartlist_quantity" data-groupid="1" value="1" size="4" class="cart_input_1881" />
  <input type="hidden" name="products_id" value="1881" />
  <input type="hidden" name="cartlist_group_id" value="1" />
</div>


推荐阅读