【问题标题】:Appending and detaching dynamically created inputs附加和分离动态创建的输入
【发布时间】:2019-07-22 18:20:27
【问题描述】:

我有两个单选按钮:

  • fixed_price_option(默认选中。)
  • variable_price_option禁用默认)

我也有两种类型的输入:

  • fixed_price_input(默认情况下可见。仅出现一次。)
  • variable_price_input(代码中不存在,因为它必须动态添加。出现一次或多次。)

When fixed_price_option is selected an input called fixed_price_input should be visable and included when later running .serialize().

fixed_price_option 被选中时,variable_price_input 不应该是可见的或在以后运行 .serialize() 时包含在内。

variable_price_option 应仅在两个日期输入之间的差异超过 12 个月时才可选。 (这个我已经解决了)

variable_price_option被选中时应该有一个更长 variable_price_input's可见,因为两个日期输入之间的全年(即durymonths + 1)。在稍后运行 .serialize() 时还需要包含它们,因此它们需要具有类似 price_year_1price_year_2price_year_3 等名称,具体取决于两个日期输入之间的整年数。

variable_price_option 被选中时,fixed_price_input 在稍后运行 .serialize() 时不应可见或包含。

我已经提供了代码。缺少的逻辑需要放在js代码底部的事件处理函数中。

关于如何解决这个问题的任何建议?

-- 更新--

我的问题需要澄清:

我正在努力的是根据选中的单选按钮来切换两种输入(fixed_price_inputvariable_price_input)的存在。隐藏/显示它们是不够的,因为我稍后会使用 .serialize() 。我应该以某种方式使用 .detach() 和 .append() 吗?

我还在为如何创建比开始日期和结束日期之间的年数多一个variable_price_input 而苦苦挣扎。我应该以某种方式使用 <template> 或 .clone() 吗?

$(document).ready(function() {

  $("#inputStartDate, #inputEndDate").change(function() {

    if ($('#inputStartDate').val() && $('#inputEndDate').val()) {

      var startDate = moment($('#inputStartDate').val());
      var endDate = moment($('#inputEndDate').val());

      var durationMonths = endDate.diff(startDate, 'months');

      $('#durationMonths').text(durationMonths);
      
      var durationYears = endDate.diff(startDate, 'years');
    
      $('#durationYears').text(durationYears);

      if (duration > 12) {
        $('#variablePriceOption').prop("disabled", false);
      } else {
        $('#variablePriceOption').prop("disabled", true);
      }

    }


  });

  $('#variablePriceOption, #fixedPriceOption').change(function() {

    if (this.value == 'fixedPrice') {
      //Logic needed
    } else if (this.value == 'variablePrice') {
      //Logic needed
    }

  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>

<div class="container">

  <div class="row mt-3">
    <div class="col">
      <div class="form-group">
        <label for="inputStartDate">Start date</label>
        <input type="date" class="form-control" id="inputStartDate" name="land_contract_start_date">
      </div>
    </div>
    <div class="col">
      <div class="form-group">
        <label for="inputEndDate">End date</label>
        <input type="date" class="form-control" id="inputEndDate" name="land_contract_end_date">
      </div>
    </div>
  </div>

  <div class="text-center">Months between selected dates = <span id="durationMonths"></span>. Years between selected dates = <span id="durationYears"></span>.
  </div>

  <div class="form-group">
    <label for="inputPriceModel">Price model</label>
    <div id="inputPriceModel">
      <div class="form-check">
        <input class="form-check-input" type="radio" name="inputPriceModel" id="fixedPriceOption" value="fixedPrice" required checked="checked">
        <label class="form-check-label" for="fixedPriceOption">
          Fixed price
        </label>
      </div>
      <div class="form-check">
        <input class="form-check-input" type="radio" name="inputPriceModel" id="variablePriceOption" value="variablePrice" disabled="disabled">
        <label class="form-check-label" for="variablePriceOption">
          Variable price
        </label>
      </div>
    </div>
  </div>

  <div class="form-group fixedPriceModelFormGroup">
    <label for="fixed_price_input">Fixed price amount</label>
    <div class="input-group">
      <input type="number" class="form-control" id="fixed_price_input" name="land_contract_fixed_annual_price">
      <div class="input-group-append">
        <span class="input-group-text">$</span>
      </div>
    </div>
  </div>

</div>

【问题讨论】:

  • 我现在已经更新/澄清了我的问题。
  • 您可以使用.detach(),但如果需要再次创建对象数据,您需要将其存储在某个地方。
  • @Twisty 谢谢!我正在考虑以某种方式使用此解决方案,但我无法弄清楚在这种情况下如何实现它:w3schools.com/jquery/….

标签: javascript jquery html


【解决方案1】:

这应该有助于您开始了解日历日期的每个年份差异的可变定价输入。代码可以分解成其他函数来处理元素的显示/隐藏等。您需要将&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"&gt;&lt;/script&gt; 代码移到其他JS 引用之上,以消除您在bootstrap 中看到的错误。

此外,您的 duration 变量应该是 durationMonths 用于比较 > 12,因为 durationundefineddurationYears 应该移到日历日期的 change 函数之外,以便您可以在其他处理函数中引用它。我在日期计算中添加了Math.abs(),以确保您处理的是正整数进行比较。

使用隐藏的inputs 上的disabled 属性将允许您序列化可见的form 数据并确保您不会获得隐藏的输入(可变定价字段等)作为@987654335 的一部分@数据。

正如@Twisty 在您帖子的 cmets 中提到的,如果您在固定/可变选项之间来回切换,您将需要使用 .detach() 或某种方式来存储可变定价输入值 (localStorage, sessionStorage 也是存储数据的选项),如果您想维护放置在变量/固定 inputs 中的任何值。如果您打算存储输入的数据值,您还需要在我的示例中删除输入字段上的 .empty() 用法。

用于确定应显示多少可变定价输入的循环函数 handleVariablePricing 需要连接到存储数据功能,以确保您使用先前输入的值创建相同数量的字段,而不是在顶部添加额外的新字段现有字段/值。

$(document).ready(function() {

  var durationYears = 0;

  $("#inputStartDate, #inputEndDate").change(function() {

    if ($('#inputStartDate').val() && $('#inputEndDate').val()) {

      var startDate = moment($('#inputStartDate').val());
      var endDate = moment($('#inputEndDate').val());

      var durationMonths = Math.abs(endDate.diff(startDate, 'months'));
      $('#durationMonths').text(durationMonths);

      // maintain value outside of change function
      durationYears = Math.abs(endDate.diff(startDate, 'years'));
      $('#durationYears').text(durationYears);

      if (durationMonths > 12) {
        $('#variablePriceOption').prop("disabled", false);
      } else {
        $('#variablePriceOption').prop("disabled", true);
      }

      // If dates changed, update variable inputs shown
      if ($('#variablePriceOption').is(':checked')) {
        if (durationMonths > 12) {
          $('#variable_price_input_1').val('');
          $('.duration-years-input').remove();
          handleVariablePricing();
        } else {
          $('#fixedPriceOption').click();
        }
      }
    }

  });

  $('#variablePriceOption, #fixedPriceOption').change(function() {

    if (this.value == 'fixedPrice') {

      $('.variablePriceModelFormGroup').removeClass('d-block').addClass('d-none');
      $('.variablePriceModelFormGroup input').each(function() {
        $(this).val('').attr('disabled', true);
      });
      $('.fixedPriceModelFormGroup input').prop('disabled', false);
      $('.fixedPriceModelFormGroup').removeClass('d-none').addClass('d-block');
      $('.duration-years-input').remove();

    } else if (this.value == 'variablePrice') {

      $('.fixedPriceModelFormGroup').removeClass('d-block').addClass('d-none');
      $('.fixedPriceModelFormGroup input').val('').attr('disabled', true);
      $('#variable_price_input_1').prop('disabled', false);
      $('.variablePriceModelFormGroup').removeClass('d-none').addClass('d-block');

      handleVariablePricing();

    }

  });

  /**
   * Creates inputs for variable pricing..
   **/
  var handleVariablePricing = function() {
    $rowClone = $('.row-main').clone();
    for (var i = 2; i <= durationYears + 1; i++) {
      $rowClone.prop('class', 'duration-years-input');
      $rowClone.find('label').text('Price Year ' + i);
      $rowClone.find('input').prop('id', 'variable_price_input_' + i);
      $rowClone.find('input').prop('name', 'land_contract_variable_annual_price_' + i);
      if ($('.duration-years-input').length === 0) {
        $('.row-main').after($rowClone);
      } else {
        $('.duration-years-input').last().after($rowClone);
      }
      $rowClone = $('.duration-years-input').last().clone();
    }
  };

  $('button').click(function() {
    console.log($('#test-form').serialize());
  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.0/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>

<div class="container">
  <form id="test-form">
    <div class="row mt-3">
      <div class="col">
        <div class="form-group">
          <label for="inputStartDate">Start date</label>
          <input type="date" class="form-control" id="inputStartDate" name="land_contract_start_date">
        </div>
      </div>
      <div class="col">
        <div class="form-group">
          <label for="inputEndDate">End date</label>
          <input type="date" class="form-control" id="inputEndDate" name="land_contract_end_date">
        </div>
      </div>
    </div>
    <div class="text-center">Months between selected dates = <span id="durationMonths"></span>. Years between selected dates = <span id="durationYears"></span>.
    </div>
    <div class="form-group">
      <label for="inputPriceModel">Price model</label>
      <div id="inputPriceModel">
        <div class="form-check">
          <input class="form-check-input" type="radio" name="inputPriceModel" id="fixedPriceOption" value="fixedPrice" required checked="checked">
          <label class="form-check-label" for="fixedPriceOption">
          Fixed price
        </label>
        </div>
        <div class="form-check">
          <input class="form-check-input" type="radio" name="inputPriceModel" id="variablePriceOption" value="variablePrice" disabled="disabled">
          <label class="form-check-label" for="variablePriceOption">
          Variable price
        </label>
        </div>
      </div>
    </div>
    <div class="form-group fixedPriceModelFormGroup">
      <label for="fixed_price_input">Fixed price amount</label>
      <div class="input-group">
        <input type="number" class="form-control" id="fixed_price_input" name="land_contract_fixed_annual_price">
        <div class="input-group-append">
          <span class="input-group-text">$</span>
        </div>
      </div>
    </div>
    <div class="form-group variablePriceModelFormGroup d-none">
      <div class="row-main">
        <label for="variable_price_input">Price Year 1</label>
        <div class="input-group">
          <input type="number" class="form-control" id="variable_price_input_1" name="land_contract_variable_annual_price_1" disabled="disabled">
          <div class="input-group-append">
            <span class="input-group-text">$</span>
          </div>
        </div>
      </div>
    </div>
  </form>
  <button>Serialize</button>
</div>

【讨论】:

  • 如果您想在 # 年的基础上额外输入变量定价,只需在 for 循环的 durationYears 变量中加 1。
  • 哇,非常感谢!我忘了提到每个variable_price_input 的标签都必须是描述性的,比如“Price year 1”、“Price year 2”等等。无论如何要解决这个问题?此外,何时检查#variablePriceOption时,如何在variable_price_input的调整何时更改开始或结束日期? span>
  • 另外,使用 Bootstrap 4 时需要自定义 css 吗?我不能只使用 .visible 和 .invisible 吗? getbootstrap.com/docs/4.3/utilities/visibility
  • 我上一条评论中的课程错误。我的意思是 .d-none 和 .d-block。 getbootstrap.com/docs/4.3/utilities/display
  • 非常感谢您的帮助。我不在乎切换时保留输入的值,因此您的解决方案是完美的!如果您认为 .d-none 和 .d-block 可以代替自定义 CSS,请告诉我。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 2020-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多