代码之家  ›  专栏  ›  技术社区  ›  jonnii

在表单中创建自定义标签字段

  •  1
  • jonnii  · 技术社区  · 15 年前

    我希望能够生成以下标记:

    <label for="field">Something <span class="hint">Field hint</span></label>
    

    form_for ... do |f|
        f.label :field, :hint => "Field hint"
    end
    

    到目前为止,我已经创建了一个初始值设定项来存储自定义功能,该功能将重新打开ActionView::Helpers::FormBuilder并更改label方法,但是我不确定将跨度实际放入标签文本中的最佳方法是什么。如果我试着直接输入文本,那么rails就会逃避内容,这是正确的。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Simone Carletti    15 年前

    您应该创建一个自定义生成器,并使用:builder参数将其传递给表单,而不是更改默认生成器。

    class HintFormBuilder < ActionView::Helpers::FormBuilder
    end
    
    form_for @resource, :builder => HintFormBuilder do |f|
    # ...
    end
    

    提示生成器继承所有FormBuilder功能,包括验证、错误消息等。现在,您应该更改需要更改的内容,以便自定义行为。

    class HintFormBuilder < ActionView::Helpers::FormBuilder
    
      (%w(label)).each do |selector|
        src = <<-end_src
          def #{selector}(method, options = {})
            hint = options.delete(:hint)
            returning(super) do |element|
              # replace here the value of element with hint 
              # if hint != nil
              # remember to use gsub! and not gsub
            end
          end
        end_src
        class_eval src, __FILE__, __LINE__
      end
    
    end
    

    根据第一条注释进行编辑:

    最好不要对Rails内部进行黑客攻击,因为现在或将来可能需要使用依赖于原始行为的插件或特性。如果不想在表单中手动附加生成器,可以创建帮助器。

    def search_form_for(记录或名称或数组,*args,&proc) 选项={:builder=>HintFormBuilder}

    form_for(record_or_name_or_array, 
             *(args << options),
             &proc)
    

    class ActionView::Helpers::FormBuilder
    
      def label_with_hint(method, text = nil, options = {})
        hint = options.delete(:hint)
        # do your own customizations...
        @template.label(@object_name, method, text, objectify_options(options))
      end
    
    end
    

    编辑: 我错了,您可以将自定义文本作为参数传递,因此不需要gsub!返回的字符串。我被文本字段标记弄糊涂了。 此时,您可以使用第一个选项(使用/不使用自定义方法进行子类化)、第二个选项(使用自定义方法进行内部攻击)或第三个选项(使用自定义方法进行内部攻击),并在将文本值发送到@template.label之前截取文本值。

    还要注意,文本可以为零。如果为nil,则该值将从方法自动生成。你应该意识到这一点。

        2
  •  1
  •   August Lilleaas    15 年前

    我会这么做的。

    # config/initializers/[anything].rb
    ActionView::Base.default_form_builder = CustomFormBuilder
    
    # lib/custom_form_builder.rb
    class CustomFormBuilder < ActionView::Helpers::FormBuilder
      def label(field, text, options = {})
        if options[:hint]
          hint = @template.content_tag(:span, options[:hint], :class => "hint")
          super(field, "#{field.to_s.humanize} #{hint}", options)
        else
          super
        end
      end
    end