Class: Brut::FrontEnd::Components::FormTag

Inherits:
Brut::FrontEnd::Component show all
Defined in:
lib/brut/front_end/components/form_tag.rb

Overview

Represents a <form> HTML element that includes a CSRF token as needed.

Instance Method Summary collapse

Methods inherited from Brut::FrontEnd::Component

component_name, #component_name

Methods included from Brut::FrontEnd::Component::Helpers

#global_component, #inline_svg

Methods included from I18n::ForHTML

#html_escape, #t

Methods included from I18n::BaseMethods

#l, #t, #t_direct, #this_field_value

Methods included from Brut::Framework::Errors

#abstract_method!, #bug!

Constructor Details

#initialize(route_params: {}, **html_attributes) { ... } ⇒ FormTag

Creates the form surrounding the contents of the block yielded to it. If the form's action is a POST, it will include a CSRF token. If the form's action is GET, it will not.

attribute can be constructed properly.

Examples:

Route without parameters

# assumes you have included Brut::FrontEnd::Components 
def view_template
  FormTag(for: NewWidgetForm, class: "new-form") do
    input(type: "text",  name: "name")
    button { "Create" }
  end
end

Route with parameters

# assumes you have included Brut::FrontEnd::Components 
def view_template
  FormTag(for: SaveWidgetWithIdForm,
          route_params: { id: widget.external_id },
          class: "new-form") do
    input(type: "text",  name: "name")
    button { "Save" }
  end
end

Parameters:

  • route_params (Hash) (defaults to: {})

    if the form requires route parameters, their values must be passed here so that the HTML action

  • html_attributes (Hash)

    any additional attributes for the <form> tag

Options Hash (**html_attributes):

  • :for (Class|Brut::FrontEnd::Form)

    the form object or class representing this HTML form or the class of a handler the form should submit to. If you pass this, you may not pass the HTML attributes :action or :method. Both will be derived from this object.

  • «any-other-key» (String)

    attributes to set on the <form> tag

Yields:

  • No parameters given. This is expected to return additional markup to appear inside the <form> element.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/brut/front_end/components/form_tag.rb', line 32

def initialize(route_params: {}, **html_attributes)
  form_class = html_attributes.delete(:for) # Cannot be a keyword arg, since for is a reserved word
  if !form_class.nil?
    if form_class.kind_of?(Brut::FrontEnd::Form)
      form_class = form_class.class
    end
    if html_attributes[:action]
      raise ArgumentError, "You cannot specify both for: (#{form_class}) and and action: (#{html_attributes[:action]}) to a form_tag"
    end
    if html_attributes[:method]
      raise ArgumentError, "You cannot specify both for: (#{form_class}) and and method: (#{html_attributes[:method]}) to a form_tag"
    end
    begin
      route = Brut.container.routing.route(form_class)
      html_attributes[:method] = route.http_method
      html_attributes[:action] = route.path(**route_params)
    rescue Brut::Framework::Errors::MissingParameter
      raise ArgumentError, "You specified #{form_class} (or an instance of it), but it requires more url parameters than were found in route_params: (or route_params: was omitted). Please add all required parameters to route_params: or use `action: #{form_class}.routing(..params..), method: [:get|:post]` instead"
    end
  end

  @csrf_token_omit_reasoning = nil

  http_method = Brut::FrontEnd::HttpMethod.new(html_attributes[:method])

  @include_csrf_token = http_method.post?
  @csrf_token_omit_reasoning = http_method.get? ? "because this form's action is a GET" : nil
  @attributes = html_attributes.merge(method: http_method)
end

Instance Method Details

#view_templateObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/brut/front_end/components/form_tag.rb', line 62

def view_template
  form(**@attributes) do
    if @include_csrf_token
      render Brut::FrontEnd::RequestContext.inject(Brut::FrontEnd::Components::Inputs::CsrfToken)
    elsif Brut.container.project_env.development?
      comment do
        "CSRF Token omitted #{@csrf_token_omit_reasoning} (this message only appears in development)"
      end
    end
    if block_given?
      yield
    end
  end
end