【问题标题】:Rails 6 create custom formtastic input based on existing oneRails 6 基于现有的创建自定义格式输入
【发布时间】:2021-06-24 23:28:42
【问题描述】:

在我的 ActiveAdmin Rails6 应用程序内部,我得到了以下部分,它替换了 editor.js 的标准输入(后面有一些 JS 魔法,与这个问题无关)。部分和渲染如下所示:

# _editor.html.erb
<%= f.input field, as: :hidden, input_html: { id: :editor_field } %>
<div style='width: 100%; background: white;' id="editorjs"></div>

# example of a parital call for field :body
<%= render 'admin/editor_js', f: f, field: :body %>

因为 ActiveAdmin 基于 formatic gem 而不是这个部分,所以我想创建和使用基于 :text 字段的自定义输入。我试图做类似下面的事情。

module CustomInputs
  class EditorJsInput < Formtastic::Inputs::TextInput
    def input_html_options
      super.merge(input_html: { id: 'editor_field' }).merge(as: :hidden)
    end
  end
end

(as: :hidden) 不起作用,不知道如何在末尾添加这个空 div &lt;div style='width: 100%; background: white;' id="editorjs"&gt;&lt;/div&gt;,这非常关键。

【问题讨论】:

    标签: ruby-on-rails formtastic


    【解决方案1】:

    as: :hidden 不是 input_html_option,而是将输入映射到 Inputs::HiddenInput 类型的input style/type;它所做的只是将输入字段呈现为隐藏列表项。此外,您覆盖 input_html_options 的方式不正确:

    # Let's say this is a line in your form input:
    input_html: { value: 'Eat plants.' } 
    
    # Your code is changing `input_html_options` to be the same as if you'd 
    # included this in your form input declaration, which doesn't make sense:
    input_html: { 
      value:      'Eat plants.', 
      input_html: { id: 'editor_field' }, 
      as:         :hidden
    }
    

    请查看有关您尝试覆盖的方法的文档和源代码:

    如果您要覆盖现有 ID,则覆盖的 input_html_options 方法将是这样的:

    # Don't recommend
    def input_html_options
      # Note: this is dangerous because the 'id' attribute should be unique
      # and merging it here instead of passing it in the field's `input_html` 
      # hash forces every input of this type to have the same id
      super.merge(id: 'editor_field')
    end
    

    假设您确实希望可靠地知道 ID,以便某些 JS 可以找到该元素并将其换出,您可以在声明表单输入时在 input_html 散列中指定它,或者更简洁地使用自动生成的 ID。 ID一般为下划线分隔的对象根键+属性名;所以如果你的表单对象是coffee: { name: 'Goblin Sludge', origin_country: 'Columbia' },我相信默认是f.input :nameid='coffee_name'渲染,f.input :origin_countryid='coffee_origin_country'渲染。您可以通过在呈现的表单上使用 devtools 检查器轻松找出这些内容。

    您似乎真的希望覆盖to_html。你需要这样的东西:

    # app/input/editor_js_input.rb
    class EditorJsInput < Formtastic::Inputs::TextInput
      def to_html
        input_wrapping do
          builder.hidden_field(method, input_html_options)
        end
      end
    end
    
    # Variation that creates a div
    class EditorJsInput < Formtastic::Inputs::TextInput
      def to_html
        input_wrapping do
          builder.content_tag(
            :div, 
            '', 
            style: 'width: 100%; background: white;', 
            id: "#{input_html_options[:id]}_editor"
          ) << builder.hidden_field(method, input_html_options)
        end
      end
    end
    # Example of what this would generate:
    # "<div style=\"width: 100%; background: white;\" id=\"coffee_name_editor\"></div><input maxlength=\"255\" id=\"coffee_name\" value=\"\" type=\"hidden\" name=\"coffee[name]\" />"
    
    
    # PARTIAL
    # This will render the div you have above:
    div style: 'width: 100%; background: white;', id: 'editorjs'
    
    # This (or a similar variant of form declaration) will render the form
    active_admin_form_for resource do |f|
      f.inputs do
        f.input :name, 
          input_html: { value: f.object.name }, 
          as: :editor_js
        f.input :origin_country, 
          input_html: { value: f.object.origin_country }, 
          as: :editor_js
      end
    end
    

    这应该将f.object.name 的输入构建为类似于&lt;input id="coffee_name" type="hidden" value="Goblin Sludge" name="coffee[name]"&gt;(请参阅FormBuilder#hidden_field

    其他想法:

    • 尝试使用Pry 之类的方法在这些方法中添加绑定,以便更好地了解它们的外观和工作方式。请注意,您需要重新启动服务器才能加载对自定义输入类中覆盖方法的更改。
    • 阅读上面引用的文档和Formtastic README;有很多真正可以访问的信息可以在这里帮助你。您还可以从 ActiveAdmin 的文档 here(以及 activeadmin.info 中提供样式元素示例的其他页面)中学习如何呈现 div
    • 评估是否需要实现Custom FormBuilder

    【讨论】:

    • 感谢您的回复。我想我可以通过使用to_htmlbuilder.input input_name, as: :hidden, input_html: { id: :editor_field } 的方法来做同样的事情。问题是如何渲染div style: 'width: 100%; background: white;' (...) 不是从局部而是从这个。我根本不想使用部分 - 换句话说,我想通过将表单声明为 editor_js 将这个 div 添加到 Formtastic 添加的所有内容中
    • 另外,如果我错了,请纠正我,但据我了解,您的解决方案与我使用 as: :hidden 而不是 as: :editor_js 相同 - 几乎相同。
    • 我用一个可以为编辑器呈现 div 的解决方案更新了上面的代码,不过我想重申,HTML 文档中的 ID 元素必须是文档中的唯一标识符(@ 987654330@),因此您不能将 ID 静态分配为“editorjs”。您使用的工具需要一个 SINGLE 容器来渲染您写入的每个脚本,并且您需要将 holderID 定义为您希望渲染到的 div 的 ID (editorjs.io/configuration)。
    • as: :hidden 大致相同,但我相信 HiddenInput 也将输入包装在隐藏列表项标签中;根据您的样式规则,这可能会阻止不稳定的 UI 事情,例如在隐藏元素周围渲染填充。同样,我建议在您的覆盖方法中添加一个绑定并使用构建器方法来找出适合您的诡计的方法。
    猜你喜欢
    • 2012-07-08
    • 2022-08-03
    • 2014-03-11
    • 1970-01-01
    • 2018-02-11
    • 2011-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多