Cocoon gem,如何在渲染关联上调用after-insert回调

时间:2017-11-02 05:59:31

标签: jquery ruby-on-rails cocoon-gem

我使用Cocoon gem构建一个嵌套表单,其中field_for包含另一个field_for。层次结构如下所示:

  • 信函表格
    • Card field_for
      • 按钮field_for

使用link_to_add_association链接添加每个卡条目。我使用after-insert回调允许用户点击创建的卡片以显示包含按钮字段的弹出窗口(用于UX目的)。

我的插入后回调示例:

$('#carousel-stage-ul')
      .on('cocoon:after-insert', function(e, insertedItem) {

        insertedItem.find('#add-card-button, .new_button_card').click(function() {
          $('#black-background')[0].style.display = "block";
          insertedItem.find('.add-button-card-modal').css('display', 'block');
        });

        insertedItem.find('#delete_new_card_button').click(function() {
          $('#black-background')[0].style.display = "none";
          insertedItem.find('.add-button-card-modal').css("display", "none");

          $firstIn = insertedItem.find('.add-button-card-modal input[type=text]').eq(0);
          $secondIn = insertedItem.find('.add-button-card-modal input[type=text]').eq(1);

          $firstIn.val("");
          $secondIn.val("");

          $buttonForm = $.parseHTML('<div id="add-card-button" class="add-button">+ Add Button</div>')
          insertedItem.find('#new_card_button').replaceWith($buttonForm[0]);

          insertedItem.find('#add-card-button, .new_button_card').click(function() {
            $('#black-background')[0].style.display = "block";
            insertedItem.find('.add-button-card-modal').css('display', 'block');
          });
        });
            })
      .on('cocoon:after-remove', function(e, insertedItem) {
        ...

_card_fields.html.erb部分呈现按钮:

<% f.object.buttons.build %>
  <%= f.fields_for :buttons do |button_card_fields| %>
      <%= render 'button_fields', f: button_card_fields %>
  <% end %>

_button_fields.html.erb partial:

<div class="add-button-card-modal">
  <h4>Add New Button</h4>
  <label>Button Text</label>
  <%= f.text_field :button_text, :maxlength => 20, placeholder: "Enter the text to display on the button..." %>
  <br><br>
  <label>Button URL</label>
  <%= f.text_field :button_url, placeholder: "Paste URL..." %>
  <div class="nav-popups-buttons">
    <button type="button" id="validate_new_card_button" class="small-cta2">Add Button</button>
    <p class="remove-link" id="delete_new_card_button">Remove Button</p>
  </div>
</div>

这是为卡片轮播中的一张卡片呈现的HTML,以便更好地理解我的插入后回调:

<div class="connected-carousels" style="display: block;">
                  <div class="stage">
                      <div class="carousel carousel-stage" data-jcarousel="true">
                          <ul id="carousel-stage-ul" style="left: 0px; top: 0px;">


                          <li class="carousel-slide">
  <div id="card-messenger">
    <div class="DIV_1b">
      <div class="DIV_2b">
        <div class="DIV_3">
          <a class="A_4"></a>
          <div class="DIV_5" style="">
          </div>
        </div>
        <div class="DIV_6">
          <div class="DIV_7">
            <div class="DIV_8">
              <div class="DIV_9">
                <div class="DIV_10">
                </div>
                <div class="DIV_11">
                  <input maxlength="80" size="0" placeholder="Enter title..." type="text" name="letter[cards_attributes][1509602161650][title]" id="letter_cards_attributes_1509602161650_title">
                </div>
              </div>
              <div class="DIV_12">
                <div class="DIV_14">
                  <input maxlength="80" size="0" placeholder="Enter subtitle..." type="text" name="letter[cards_attributes][1509602161650][subtitle]" id="letter_cards_attributes_1509602161650_subtitle">
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div id="add-card-button" class="add-button" style="width: 308.203px;">+ Add Button</div>
      <div id="DIV_19" class="card-share-button" style="display:none;">
        <a id="A_20">Share</a>
      </div>
      <div id="DIV_19" class="input-card-share-button">
        <div id="add-share-card-button" class="add-button" style="padding: 0!important;">+ Add Share</div>
      </div>
      <input value="false" id="hidden-share-field" type="hidden" name="letter[cards_attributes][1509602161650][button_share]">
    </div>
  </div>

    <div class="add-button-card-modal">
      <h4>Add New Button</h4>
      <label>Button Text</label>
      <input maxlength="20" placeholder="Enter the text to display on the button..." size="20" type="text" name="letter[cards_attributes][1509602161650][buttons_attributes][0][button_text]" id="letter_cards_attributes_1509602161650_buttons_attributes_0_button_text">
      <br><br>
      <label>Button URL</label>
      <input placeholder="Paste URL..." type="text" name="letter[cards_attributes][1509602161650][buttons_attributes][0][button_url]" id="letter_cards_attributes_1509602161650_buttons_attributes_0_button_url">
      <div class="nav-popups-buttons">
        <button type="button" id="validate_new_card_button" class="small-cta2">Add Button</button>
        <p class="remove-link" id="delete_new_card_button">Remove Button</p>
      </div>
    </div>
  <div class="modal-image">
    <div id="display_image_upload">
      <label>Upload Image</label>
      <input id="image-input" class="inputBox_upload_image" type="file" name="letter[cards_attributes][1509602161650][image_url]"><div class="progress"><div class="bar"></div></div>
    </div>
    <label id="or">OR</label>
    <div id="display_image_url">
      <label>Paste Image Url</label>
      <input id="image-input" class="inputBox_image" type="text" name="letter[cards_attributes][1509602161650][remote_image_url]">
    </div>
    <div class="nav-popups-buttons">
      <button type="button" id="validate_image" class="small-cta2">Add Image</button>
      <p class="remove-link" id="delete_new_card_image">Remove Image</p>
    </div>
  </div>
  <div>
    <input type="hidden" name="letter[cards_attributes][1509602161650][_destroy]" id="letter_cards_attributes_1509602161650__destroy" value="false"><a class="remove-link remove_fields dynamic" data-wrapper-class="carousel-slide" href="#">Remove Card</a>
  </div>
</li></ul>
                        </div>
                        <a href="#" class="prev prev-stage inactive" data-jcarouselcontrol="true"><span>‹</span></a>
                        <a href="#" class="next next-stage inactive" data-jcarouselcontrol="true"><span>›</span></a>
                    </div>
              <div class="navigation">
                  <a href="#" class="prev prev-navigation inactive" data-jcarouselcontrol="true">‹</a>
                  <a href="#" class="next next-navigation inactive" data-jcarouselcontrol="true">›</a>
                  <div class="carousel carousel-navigation" data-jcarousel="true">
                    <ul id="carousel-navigation-ul" style="left: 0px; top: 0px;"><li data-jcarouselcontrol="true" class="active"><img alt="botletter" class="carousel-ico" src="/assets/icon-cards-0178dc5a1fb2811909dcd1d1fcef121baa165e46d49973dff5fdea12090631fa.png"></li></ul>
                  </div>
              </div>
              <div>
                <a id="add-card-button-bis" data-association-insertion-node="#carousel-stage-ul" data-association-insertion-method="append" class="add_fields" data-association="card" data-associations="cards" data-association-insertion-template="<li class=&quot;carousel-slide&quot;>
  <div id=&quot;card-messenger&quot;>
    <div class=&quot;DIV_1b&quot;>
      <div class=&quot;DIV_2b&quot;>
        <div class=&quot;DIV_3&quot;>
          <a class=&quot;A_4&quot;></a>
          <div class=&quot;DIV_5&quot; style=&quot;&quot;>
          </div>
        </div>
        <div class=&quot;DIV_6&quot;>
          <div class=&quot;DIV_7&quot;>
            <div class=&quot;DIV_8&quot;>
              <div class=&quot;DIV_9&quot;>
                <div class=&quot;DIV_10&quot;>
                </div>
                <div class=&quot;DIV_11&quot;>
                  <input maxlength=&quot;80&quot; size=&quot;0&quot; placeholder=&quot;Enter title...&quot; type=&quot;text&quot; name=&quot;letter[cards_attributes][new_cards][title]&quot; id=&quot;letter_cards_attributes_new_cards_title&quot; />
                </div>
              </div>
              <div class=&quot;DIV_12&quot;>
                <div class=&quot;DIV_14&quot;>
                  <input maxlength=&quot;80&quot; size=&quot;0&quot; placeholder=&quot;Enter subtitle...&quot; type=&quot;text&quot; name=&quot;letter[cards_attributes][new_cards][subtitle]&quot; id=&quot;letter_cards_attributes_new_cards_subtitle&quot; />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div id=&quot;add-card-button&quot; class=&quot;add-button&quot; style=&quot;width: 308.203px;&quot;>+ Add Button</div>
      <div id=&quot;DIV_19&quot; class=&quot;card-share-button&quot; style=&quot;display:none;&quot;>
        <a id=&quot;A_20&quot;>Share</a>
      </div>
      <div id=&quot;DIV_19&quot; class=&quot;input-card-share-button&quot;>
        <div id=&quot;add-share-card-button&quot; class=&quot;add-button&quot; style=&quot;padding: 0!important;&quot;>+ Add Share</div>
      </div>
      <input value=&quot;false&quot; id=&quot;hidden-share-field&quot; type=&quot;hidden&quot; name=&quot;letter[cards_attributes][new_cards][button_share]&quot; />
    </div>
  </div>

    <div class=&quot;add-button-card-modal&quot;>
      <h4>Add New Button</h4>
      <label>Button Text</label>
      <input maxlength=&quot;20&quot; placeholder=&quot;Enter the text to display on the button...&quot; size=&quot;20&quot; type=&quot;text&quot; name=&quot;letter[cards_attributes][new_cards][buttons_attributes][0][button_text]&quot; id=&quot;letter_cards_attributes_new_cards_buttons_attributes_0_button_text&quot; />
      <br><br>
      <label>Button URL</label>
      <input placeholder=&quot;Paste URL...&quot; type=&quot;text&quot; name=&quot;letter[cards_attributes][new_cards][buttons_attributes][0][button_url]&quot; id=&quot;letter_cards_attributes_new_cards_buttons_attributes_0_button_url&quot; />
      <div class=&quot;nav-popups-buttons&quot;>
        <button type=&quot;button&quot; id=&quot;validate_new_card_button&quot; class=&quot;small-cta2&quot;>Add Button</button>
        <p class=&quot;remove-link&quot; id=&quot;delete_new_card_button&quot;>Remove Button</p>
      </div>
    </div>
  <div class=&quot;modal-image&quot;>
    <div id=&quot;display_image_upload&quot;>
      <label>Upload Image</label>
      <input id=&quot;image-input&quot; class=&quot;inputBox_upload_image&quot; type=&quot;file&quot; name=&quot;letter[cards_attributes][new_cards][image_url]&quot; />
    </div>
    <label id=&quot;or&quot;>OR</label>
    <div id=&quot;display_image_url&quot;>
      <label>Paste Image Url</label>
      <input id=&quot;image-input&quot; class=&quot;inputBox_image&quot; type=&quot;text&quot; name=&quot;letter[cards_attributes][new_cards][remote_image_url]&quot; />
    </div>
    <div class=&quot;nav-popups-buttons&quot;>
      <button type=&quot;button&quot; id=&quot;validate_image&quot; class=&quot;small-cta2&quot;>Add Image</button>
      <p class=&quot;remove-link&quot; id=&quot;delete_new_card_image&quot;>Remove Image</p>
    </div>
  </div>
  <div>
    <input type=&quot;hidden&quot; name=&quot;letter[cards_attributes][new_cards][_destroy]&quot; id=&quot;letter_cards_attributes_new_cards__destroy&quot; value=&quot;false&quot; /><a class=&quot;remove-link remove_fields dynamic&quot; data-wrapper-class=&quot;carousel-slide&quot; href=&quot;#&quot;>Remove Card</a>
  </div>
</li>
" href="#" style="display: block;">+ Add Card</a>
              </div>
            </div>

它看起来像这样: The Card after clicking on the link_to_add_association link

The button popup after clicking on Add Button, displaying the button fields

除非创建操作引发错误或加载编辑视图,否则一切正常。在这两种情况下,已经创建了已创建的卡,但未调用后插入回调。因此,我无法显示我的按钮弹出窗口......

有没有办法在编辑视图/错误视图中调用渲染后关联的插入后回调?

2 个答案:

答案 0 :(得分:2)

如果我理解正确,您希望after-insert回调中的内容也是服务器呈现的html。这在某种意义上是奇怪的,因为imho实际上是我先做的事情:)

因此,不是附加点击事件,而是始终处理它们(动态)。请注意id - 元素只允许一次页面(正确的html,否则会导致很多错误),所以我用类似的替换所有那些,因为它们似乎在重复。

所以做一些像

这样的事情
$(document).on('click', '.add-card-button, .new-button-card'), function() {
  $('#black-background')[0].style.display = "block";
  $(this).nearest('.add-button-card-modal').css('display', 'block');
}) 

有人可能想知道为什么你不使用普通的模态库,就像普通人一样:P

第二个单击处理程序虽然稍微复杂一点,实际上会以同样的方式解决,因此不再需要after-insert处理程序。

类似

$(document).on('click', '.delete-card-button', function() {
  ...
})

答案 1 :(得分:1)

你真的不应该使用jquery来修复这样的编辑代码......这是一个症状,而不是问题...如果关系&amp; .build设置正确,编辑将正常工作&amp;自动加载所有内容 - 因为rails会生成表单的hmtl。

在您真正尝试使用jquery hacks修复代码之前 - 我建议您构建一个没有弹出窗口的页面......这一切都只是在一个大混乱中吐出来。如果嵌套模型适用于您当前的关系,那么请继续实现复杂的弹出系列。如果它不起作用 - 问题是您在模型中的关系或控制器使用.build 的方式

据说你要找的答案可以在jquery中采用两种形式:

  1. 常规 - 您使用$( document ).ready()检测何时设置为触发包含对cocoon.js的{​​{1}}回调调用的函数。
  2. 具体 - 由于您可能知道包含按钮after-insert的名称或css元素,因此您首先要创建一个选择器,以便在field_for ...之后的css后面进行查找可能是field_for。你这样做,所以jquery不会在你的dom&amp;事故中改变其他部分。然后使用jquery .on() 指定按钮所属类型的所有dom元素,以及触发的触发器。