Adding/Removing Cocoon 嵌套字段

Adding/Removing Cocoon Nested Fields

我正在使用很棒的 gem Cocoon 根据用户可以 select 的 "length" 值生成嵌套字段。我的问题是我需要找到一种方法来检查有多少嵌套字段已经添加到表单中,然后只添加当前不在表单中的字段。例如:

用户将长度值设置为 2,有 2 组嵌套字段可供使用。现在用户想要将他们的值更改为 3,这就是我 运行 遇到困难的地方。我不完全确定如何根据更改后的值 add/remove 字段,而不仅仅是删除所有字段并重新 运行 插入嵌套字段。下面是一些代码供参考:

HTML

<div class="row px-md-4">
  <div class="col-12">
    <div class="d-flex flex-column pb-3">
      <h2 class="f-500 dark_grey_text pt-3" style="font-size:1.8em;">Itinerary Details</h2>
      <p class="f-300">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    </div>
  </div>
  <div class="col-12 py-3">
    <div class="form-group">
      <h6>Set your length</h6>
      <%= f.number_field :length, placeholder:"How many days is your adventure?", value: number_with_precision(f.object.length, precision: 2), step: 1, class: 'stepper_navtext form-control', id: 'length' %>
    </div>
  </div>

  <div class="col-12 py-3">
    <div class="form-row mb-3" id="days">
      <div class="nav nav-pills" id="tab-menu" role="tablist">

      </div>

      <div class="tab-content" id="itinerary-tab-content">

      </div>

        <div id='itineraries' class='w-100 itineraries'>
          <%= f.fields_for :itineraries do |itinerary| %>
            <%= render 'adventure/listings/forms/itinerary_fields', :f => itinerary %>
          <% end %>
          <div class='links'>
            <%= link_to_add_association 'add day', f, :itineraries, partial: 'adventure/listings/forms/itinerary_fields', class:"d-none" %>
          </div>
        </div>
    </div>
  </div>
</div>

JS

$('#length').on('focusin', function(){
    console.log("Saving value " + $(this).val());
    $(this).data('val', $(this).val());
});

$( "#length" ).change(function() {

      var prev = $(this).data('val');
      var current = $(this).val();
      console.log("Prev value " + prev);
      console.log("New value " + current);

      $('#tab-menu').empty();

      $('.nested-fields').remove();

      let days = $('#length').val();
      var i;
      var counter = current - prev;
      console.log('The difference is' + counter);
      var text_max = 40;

      for (i = 0; i < days; i++) {
        var new_id;
        $(".links").find(">:first-child").trigger("click");
      }  ...

我找到的唯一解决方案是清除表单中的所有字段,并重新生成对 Cocoon 中添加关联按钮的点击。这对我来说似乎很老套,而且我认为我这样做的方式不正确:/。任何建议将不胜感激!

恕我直言,你非常接近,所以我想知道是什么阻碍了你真正找到解决方案。所以让我先用伪代码解释一下(当某些问题似乎无法解决时,这总是对我有帮助):

  • 当长度改变时
  • 检查长度如何变化
  • 如果长度增加:添加字段
  • 如果减少:删除后面的字段

所以在代码中,这可能看起来像

$( "#length" ).change(function() 
  var prev = $(this).data('val');
  var current = $(this).val();

  if (current > prev) {
    var days_to_add = current - prev; 
    for (i = 0; i < days_to_add; i++) {
      $(".links").find(">:first-child").trigger("click");
    }  
  } else {
    var days_to_remove = prev - current; 
    for (i = 0; i < days_to_remove; i++) {
      $('#itineraries .nested-fields').last().remove();  
    }  
  }

我不完全确定你的 prev / current 是否设置正确,除非你设置 data('val'),但因为 prev 只是当前可见的日子,你也可以做类似的事情:

var prev = $("#itineraries .nested-fields:visible').length; 
var current = $this.val();

(为什么要使用 :visible?因为如果您还允许在编辑时删除字段,我们必须 "hide" 字段而不是仅仅删除它们)

这提醒了我:如果您确实显示了 link_to_remove_association,则最好单击它,或者如果您将其添加为 "hidden",因为这将使您的表单保持正确。这仅适用于您还允许编辑现有表单的情况,因为在这种情况下,我们需要保留带有 _destroy 标志集的嵌套子项,以便 rails 可以在保存表单时销毁它。