iblue
iblue

Reputation: 30404

Automatically add hidden field to form

I am trying to build a custom form builder in simple_form, which add some hidden fields to a form without using form.hidden_field. I noticed that the utf8 and authenticity_token hidden fields are automatically added to every form.

Is there a similar mechanism to add another custom hidden field, but only to forms that are generated by my custom form builder?

Upvotes: 0

Views: 664

Answers (3)

iblue
iblue

Reputation: 30404

The secret ist to use capture, which allows you to get the HTML generated in the template. You can then add hidden fields using the form.hidden_field method (in fact any method), which returns the generated HTML directly.

def custom_form_for(object, *args, &block)
  options = args.extract_options!.merge(builder: CustomFormBuilder)

  simple_form_for(object, *(args << options)) do |form|
    capture do
      block.call(form)
    end.tap do |content|
      content << form.hidden_field "foo", value: "bar"
      content << form.hidden_field "baz", value: "qux"
      # ...
    end
  end
end

Upvotes: 1

TheConstructor
TheConstructor

Reputation: 4465

You could extend your custom_form_for mehtod like this

def custom_form_for(object, *args, &block)
  options = args.extract_options!
  simple_form_for(object, *(args << options.merge(:builder => CustomFormBuilder))) do |form|
    block.call(form) << form.input_field(:field, :as => :hidden, :value => 'value')
  end
end

The hidden field will be the last element of the form; if you switch the lines it will be the first.

Upvotes: 1

lipanski
lipanski

Reputation: 1763

Instead of patching this at FormBuilder level, you can integrate this into a custom input:

class MagicInput < SimpleForm::Inputs::HiddenInput
  def input
    if object.condition?
      @builder.hidden_field(:hidden_field_name, value: "some value").html_safe
      # You could also call #super here (instead of the previous call)
      # because this extends HiddenInput (might be cleaner, depending on what you
      # want to achieve)
    end
  end
end

This custom input injects a hidden field into your form only if object.condition? is true. Obviously you'll need to create the #condition? method on the object passed to your form (or replace this condition line with wathever floats your boat).

Then in your view you'd call it like:

= f.input :something, as: :magic

And your hidden field will appear only when object.condition? passes.

Edit: And for the juicy detials - the utf8 and authenticity_token hidden fields are implemented in form_tag - not really in the FormBuilder: https://github.com/rails/rails/blob/801e159ce2f4645f6839c94ab0febf97a0d8543d/actionview/lib/action_view/helpers/form_tag_helper.rb#L713

Upvotes: 6

Related Questions