Class: Brut::FrontEnd::Components::Inputs::SelectTagWithOptions

Inherits:
Brut::FrontEnd::Components::Input show all
Defined in:
lib/brut/front_end/components/inputs/select_tag_with_options.rb

Overview

Renders an HTML <select>.

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(form:, input_name:, options:, include_blank: false, value_attribute:, option_text_attribute:, index: nil, html_attributes: {}) ⇒ Brut::FrontEnd::Components::Inputs::SelectTagWithOptions

Creates the appropriate select input for the given Form and input name. Generally, you want to use this method over the initializer.

Parameters:

  • form (Brut::FrontEnd::Form)

    The form that is being rendered. This method will consult this class to understand the requirements on this select so its HTML is generated correctly.

  • input_name (String)

    the name of the input, which should be a member of form

  • options (Array<Object>)

    An array of objects represented what is being selected. These can be any object and are ideally whatever domain object or data type you want on the backend to represent this selection.

  • value_attribute (Symbol|String)

    the name of an attribute to determine an option's value. This will be called on each element of options to get the value used for the <option>'s value attribute. The value returned by value_attribute should be unique amongst the options provided and be distinct from whatever value is used for include_blank.

  • option_text_attribute (Symbol|String)

    the name of an attribute to determine the text for an option. This will be called on each element of options to get the value used for the <option>'s text content. The value returned by option_text_attribute need not be unique, though if it is not unique, it will certainly be confusing.

  • index (Integer) (defaults to: nil)

    if this input is part of an array, this is the index into that array. This is used to get the input's value.

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

    any additional HTML attributes to include on the <select> element.

  • include_blank (false|true|Hash) (defaults to: false)

    configure how and if to include a blank element in the select. If this is false, there will be no blank element. If it's true, there will be one with no value or text. If this is a Hash it must contain a value: key and a text_content: key to be used as the value attribute and option text content, respectively.



30
31
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/brut/front_end/components/inputs/select_tag_with_options.rb', line 30

def initialize(form:,
               input_name:,
               options:,
               include_blank: false,
               value_attribute:,
               option_text_attribute:,
               index: nil,
               html_attributes: {})
  html_attributes = html_attributes.map { |key,value| [ key.to_sym, value ] }.to_h
  default_html_attributes = {}
  index ||= 0
  input = form.input(input_name, index:)
  default_html_attributes[:required] = input.required
  if !form.new? && !input.valid?
    default_html_attributes["data-invalid"] = true
    input.validity_state.each do |constraint,violated|
      if violated
        default_html_attributes["data-#{constraint}"] = true
      end
    end
  end
  name = if input.array?
           "#{input.name}[]"
         else
           input.name
         end

  input_value = input.value

  @options                = options
  @include_blank          = IncludeBlank.from_param(include_blank)
  @value_attribute        = value_attribute
  @option_text_attribute  = option_text_attribute
  @html_attributes        = default_html_attributes.merge(html_attributes)
  @html_attributes[:name] = name

  if input_value.nil?
    @selected_value = nil # explicitly nothing is selected
  else
    if input_value.kind_of?(Array)
      raise "WTF: #{name}" # XXX?
    end
    option = options.detect { |option|
      input_value == option.send(@value_attribute)
    }
    if option.nil?
      raise ArgumentError, "selected_value #{input_value} was not the value for #{value_attribute} on any of the options: #{options.map { |option| option.send(value_attribute) }.join(', ')}"
    end
    @selected_value = option.send(@value_attribute)
  end
end

Instance Method Details

#view_templateObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/brut/front_end/components/inputs/select_tag_with_options.rb', line 82

def view_template
  select(**@html_attributes) {
    if @include_blank
      option(**@include_blank.option_attributes) {
        @include_blank.text_content
      }
    end
    options = @options.each do |option|
      value = option.send(@value_attribute)
      option_attributes = { value: value }
      if value == @selected_value
        option_attributes[:selected] = true
      end
      option(**option_attributes) {
        option.send(@option_text_attribute)
      }
    end
  }
end