在rails中如何为`checkbox`定义自定义表单标签,如`md-checkbox`?

时间:2015-06-24 15:31:44

标签: ruby-on-rails ruby-on-rails-4

我试图在轨道上使用带有红宝石的Angular Material。在Angular Material中,我们大量使用自定义html标签。例如,对于复选框,我们使用<md-checkbox>。在rails中,当我们调用f.check_box时,它会生成标准的html标记。如何为此添加自定义标记?

1 个答案:

答案 0 :(得分:1)

我建议你制作一个自定义表单构建器来更好地管理它(当然,如果只需要自定义HTML标记的几个地方,你也可以使用content_tag。)

尝试将此添加到app/helpers/angular_form_helper.rb

module AngularFormHelper
  class FormBuilder < ActionView::Helpers::FormBuilder
    def check_box(method, options = {}, checked_value = "1", unchecked_value = "0", &block)
      Tags::MdCheckBox.new(@object_name, method, @template, checked_value, unchecked_value, objectify_options(options)).render(&block)
    end

    def submit(value=nil, options={})
      value, options = nil, value if value.is_a?(Hash)
      value ||= submit_default_value
      @template.angular_button_tag(value, options)
    end
  end

  module Tags
    class Base < ActionView::Helpers::Tags::Base
      def add_default_name_and_id(options)
        super(options)
        options["ng-model"] = options["name"]
        options.delete("name")
      end
    end

    class MdCheckBox < Base
      def initialize(object_name, method_name, template_object, checked_value, unchecked_value, options)
        @checked_value   = checked_value
        @unchecked_value = unchecked_value
        super(object_name, method_name, template_object, options)
      end

      def render(content = nil, &block)
        options = @options.stringify_keys
        options["ng-true-value"]    = @checked_value
        options["ng-false-value"]   = @unchecked_value

        add_default_name_and_id(options)

        content = block_given? ? @template_object.capture { yield || "" } : ""

        content_tag("md-checkbox", content, options)
      end
    end
  end

  def angular_button_tag(content_or_options = nil, options = nil, &block)
    if content_or_options.is_a? Hash
      options = content_or_options
    else
      options ||= {}
    end

    options = { 'type' => 'submit' }.merge!(options.stringify_keys)

    if block_given?
      content_tag "md-button", options, &block
    else
      content_tag "md-button", content_or_options || 'Button', options
    end
  end

  def angular_form_for(record_or_name_or_array, *args, &block)
    options = args.extract_options!.symbolize_keys
    options[:html] = {} unless options[:html].present?
    options[:html]["ng-submit"] = options.delete(:submit)
    options[:url] = "#"
    form_for(record_or_name_or_array, *(args << options.merge(builder: FormBuilder)), &block)
  end
end

然后用这个构建表单:

<%= angular_form_for @resource, submit: "submit()" do |f| %>
    <%= f.check_box(:field1) do %>
        Field 1
    <% end %>
    <%= f.submit %>
<% end %>

它会产生这样的东西:

<form ng-submit="submit()" class="edit_resource" id="edit_resource_1" action="#" accept-charset="UTF-8" method="post">
    ...
    <md-checkbox ng-true-value="1" ng-false-value="0" id="resource_field1" ng-model="resource[field1]">
        Field 1
    </md-checkbox>
    <md-button type="submit">Update Resource</md-button>
</form>