【问题标题】:Unique Nested Child Identifiers for Tab Links using Twitter Bootstrap & Cocoon使用 Twitter Bootstrap 和 Cocoon 的标签链接的唯一嵌套子标识符
【发布时间】:2013-02-01 19:11:05
【问题描述】:

我有一个 Ruby on Rails 应用程序,其中一部分包含 Twitter Bootstrap 选项卡,用户可以使用 Simple Form 和 Cocoon 添加该部分的多个实例。

为了使选项卡链接正常工作,我必须为部分的每个新子项中的选项卡设置唯一名称(以便单击特定选项卡会激活其自己的唯一内容,而不是相同选项卡的内容前一个子部分中的名称出现在同一页面上)。

我看到代码被添加到 Cocoon 来实现这个目标:https://github.com/nathanvda/cocoon/pull/100

在那次讨论中,有迹象表明新功能已在 Cocoon Simple Form Demo 项目中进行了试用。但是在尝试新功能的过程中所做的任何更改都没有在那里提交(至少据我所知)。

查看 github 上的提交,似乎已在 Cocoon javascript 代码中通过在“insertionNode.trigger”调用 (https://github.com/woto/cocoon/commit/cb206d501e4749a05e0c1d868911da159c8200c1) 的参数中添加“[contentNode]”来完成添加:

insertionNode.trigger('cocoon:before-insert', [contentNode]);

我对这些东西不是很熟练。

那么,如何实现/获取嵌套子项的每个新实例的唯一标识符?

任何帮助或指导将不胜感激。

这是我的应用程序中的代码供参考:

-# /app/controllers/parent_records_controller.rb

class ParentRecordsController < ApplicationController

  # GET /parent_records/1/edit
  def edit
    @parent_record = ParentRecord.find(params[:id])
    @parent_record.items.build
  end
end

-#/app/views/parent_records/_form.html.haml

.row-fluid
  =simple_form_for(@parent_record, :wrapper => :inline4, :html => {:class => 'form-inline', :multipart => true}) do |f|
    .row-fluid
      = f.simple_fields_for :items do |item|
        =render :partial => '/parent_records/form_partials/item', :locals => { :f => item }
      .row
        .span2.offset9
          = link_to_add_association 'Add Another Item', f, :items, :class => 'btn btn-primary', :partial =>     'parent_records/form_partials/item'
    = f.button :submit , :class => 'btn btn-success'

-#/app/views/parent_records/form_partials/_item ------ TAB HREF NAME is where I need the UNIQUE IDENTIFIERS ------

.nested-fields
  .well.span
    .tabbable
      %ul.nav.nav-tabs
        %li.active
          %a{"data-toggle" => "tab", :href => "#tab1"} Item Info 
        %li
          %a{"data-toggle" => "tab", :href => "#tab2"} Pictures

      .tab-content
        #tab1.tab-pane.active
          = f.input :short_name,:label => 'Item Title'
          = f.input :brand,:label => 'Brand'
          = f.input :description,:label => 'Description' 

        #tab2.tab-pane
          = f.simple_fields_for :pictures do |picture|
            =render :partial => '/parent_record/form_partials/picture', :locals => { :f => picture }
          .span2.offset9
            = link_to_add_association 'Add A Picture', f, :pictures, :class => 'btn btn-primary', :partial =>     'parent_records/form_partials/picture'
      .span2
        = link_to_remove_association "Remove Item", f, :class => 'btn btn-danger'

-#/app/views/parent_records/form_partials/_picture

.nested-fields  
  .well.span
    = f.input :image,   :label => 'Seclect Image to be Uploaded'
    = f.input :rank,    :label => 'Image Rank for this Item'
    .row
      .span2
        = link_to_remove_association "Remove Picture", f, :class => 'btn btn-danger'

编辑/后续问题:

下面 Nathan 的回答适用于添加唯一标识符,但添加唯一标识符破坏了 Bootstrap 的选项卡功能。鉴于我的印象是 Bootstrap javascript 可能仅在文档最初加载时评估选项卡和链接之间的对应关系,这似乎是有道理的。

谁能告诉我如何让 Bootstrap javascript 重新初始化并找到新的 id 和链接?

EDIT2

原来(我认为)是分隔 .nested-fields.tabbable 的 div .well.span 阻止了 Bootstrap 能够初始化新命名的 href 和选项卡 ID。疯狂的旅程,但最终令人满意。

【问题讨论】:

  • 据我了解您的问题,每次单击链接时,您都会有一个部分加载 ajax 并附加到您的表单中。由于我们只能在客户端时知道页面上存在哪些选项卡 ID,因此我建议在插入 ID 后使用after-insert 回调来调整 ID(即扫描所有存在的 ID 并递增)+ 启动选项卡.不是最好的解决方案,但仍然。另一种选择是首先使用 object_id (f.object.object_id) 生成唯一的选项卡 ID。
  • @m_x 感谢您的建议。我当然认为您的“插入后”回调想法会奏效。我只是不知道该怎么做。
  • @m_x 抱歉,我的评论被分成了两部分。我只是尝试了关于object_id 的想法。当添加每个新的“项目”(使用f.object_idf.object.object_id)时,我可以获得一个在表单表单中显示的对象 ID,但是每个新的孩子都会打印相同的“object_id”(这告诉我我没有抓住正确的对象)。似乎simple_fields_for 传递到块中的任何东西对于每个孩子来说都是同一个对象。我需要弄清楚得到实际的@item 对象。有什么提示吗?
  • 很奇怪。表单构建器对象应该是嵌套对象......我的猜测是您访问的是父对象。也许您使用了错误的 f ?我倾向于以不同的方式命名我的子表单构建器以避免此类错误......或者也许有一个我不知道 simple_form 的微妙之处
  • @m_x 是的,我考虑过我错误地处理parent_record 对象的可能性。有一件事让我远离了这种可能性:我在控制器中构建的 item 对象(与 Cocoon 通过 ajax 构建的子 item 对象相反)具有不同的 object_id。我仍在尝试解决这个问题,但我猜有一种相当简单的方法可以获取这个现在内置于 Cocoon 中的唯一 ID(通过上述对源代码的添加)。我只是不知道该怎么做(但至少我知道它存在,这是伟大的第一步,哈哈)。谢谢!

标签: ruby-on-rails twitter-bootstrap simple-form nested-forms cocoon-gem


【解决方案1】:

首先,在cocoon_simple_form_demo 项目中,您将看到最后一次提交使用cocoon:before-insertcocoon:after-insert 事件添加了动画。

after_insert 事件为您提供插入的 DOM 元素,因此您可以使用它做任何您喜欢的事情,例如填写唯一的href。

所以在你的情况下,这将类似于以下内容(注意:完全未经测试的代码,但我希望它能让你继续前进):

$('form').bind('cocoon:before-insert', function(e,item_to_be_added) {
    new_id = new Date().getTime();
    item_to_be_added.find('a[href="#tab1"]').attr('href', "#tab1_" + new_id);
    item_to_be_added.find('#tab1').attr('id', "tab1_" + new_id);
    // do the same for #tab2
});

这只是标准的 jquery DOM 操作。希望这会有所帮助。

您可以在插入后重新触发选项卡行为(这需要在插入后,否则没有用处):

   $('form').bind('cocoon:after-insert', function(e,item_to_be_added) {
       $('nav-tabs a').click(function(e) {
         e.preventDefault();
         $(this).tab('show');
       }); 
   });

您应该已经有了这样的代码?另一种选择是使用更好的on,像这样:

$('form').on 'click', '.nav-tabs a', function(e) {
    e.preventDefault(); 
    $(this).tab('show');
});

这应该只需要在页面加载时执行一次,并且在添加选项卡时这将继续工作。

HTH。

【讨论】:

  • 非常感谢内森的回复! Jquery DOM-manipulation 还不是我的工具库中的工具,但是通过您的示例和我将要做的研究,它即将成为一个工具。几个快速提炼的问题:1)您提到after_insert 事件给出了插入的DOM 元素,但您的示例似乎使用了cocoon:before-insert 事件。那是错字吗?或者,是我的无知导致我偏离轨道?
  • 更正:这只是一个精炼问题。谢谢!马利克
  • 请忽略前面的问题。答案在您的帖子中:可以在插入之前或之后进行更改。两者都有效。通过您的示例和有关在演示应用程序中查看位置的提示,完成它实际上非常容易。我能够使用这两种方法 (cocoon:before-insert' and cocoon:after-insert`) 获得我正在寻找的唯一 ID,但是,这样做显然会破坏 Bootstrap 的选项卡功能。
  • 我认为在这种情况下 Bootstrap 选项卡功能会中断是有道理的,因为我猜 Bootstrap javascript 可能只在页面最初加载时检查选项卡 hrefid。一旦名称更改,您能想出任何方法来触发 Bootstrap javascript 以重新初始化选项卡吗?这是一个非常有教育意义的兔子洞。谢谢
  • 您将不得不重新触发引导选项卡行为,现在肯定是after-insert,类似于$("your-tab-container").tabs()(因为否则引导将不会做必要的事情)。 HTH。
猜你喜欢
  • 2012-09-05
  • 1970-01-01
  • 2014-06-18
  • 1970-01-01
  • 2012-06-10
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
相关资源
最近更新 更多