Class: Decidim::FormBuilder

Inherits:
FoundationRailsHelper::FormBuilder
  • Object
show all
Includes:
ActionView::Context
Defined in:
lib/decidim/form_builder.rb

Overview

This custom FormBuilder adds fields needed to deal with translatable fields, following the conventions set on ‘Decidim::TranslatableAttributes`.

Direct Known Subclasses

AuthorizationFormBuilder, FilterFormBuilder

Instance Method Summary collapse

Instance Method Details

#categories_select(name, collection, options = {}) ⇒ Object

Public: Generates a select field with the categories. Only leaf categories can be set as selected.

name - The name of the field (usually category_id) collection - A collection of categories. options - An optional Hash with options:

  • prompt - An optional String with the text to display as prompt.

  • disable_parents - A Boolean to disable parent categories. Defaults to ‘true`.

Returns a String.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/decidim/form_builder.rb', line 111

def categories_select(name, collection, options = {})
  options = {
    disable_parents: true
  }.merge(options)

  disable_parents = options[:disable_parents]

  selected = object.send(name)
  categories = categories_for_select(collection)
  disabled = if disable_parents
               disabled_categories_for(collection)
             else
               []
             end

  select(name, @template.options_for_select(categories, selected: selected, disabled: disabled), options)
end

#check_box(attribute, options = {}, checked_value = "1", unchecked_value = "0") ⇒ Object

Public: Override so checkboxes are rendered before the label.



130
131
132
133
134
135
136
# File 'lib/decidim/form_builder.rb', line 130

def check_box(attribute, options = {}, checked_value = "1", unchecked_value = "0")
  custom_label(attribute, options[:label], options[:label_options], true) do
    options.delete(:label)
    options.delete(:label_options)
    @template.check_box(@object_name, attribute, objectify_options(options), checked_value, unchecked_value)
  end + error_and_help_text(attribute, options)
end

#collection_check_boxes(attribute, collection, value_attribute, text_attribute, options = {}, html_options = {}) ⇒ Object

Public: generates a check boxes input from a collection and adds help text and errors.

attribute - the name of the field collection - the collection from which we will render the check boxes value_attribute - a Symbol or a Proc defining how to find the value

attribute

text_attribute - a Symbol or a Proc defining how to find the text

attribute

options - a Hash with options html_options - a Hash with options

Renders a collection of check boxes. rubocop:disable Metrics/ParameterLists



25
26
27
# File 'lib/decidim/form_builder.rb', line 25

def collection_check_boxes(attribute, collection, value_attribute, text_attribute, options = {}, html_options = {})
  super + error_and_help_text(attribute, options)
end

#date_field(attribute, options = {}) ⇒ Object

Public: Override so the date fields are rendered using foundation datepicker library



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/decidim/form_builder.rb', line 140

def date_field(attribute, options = {})
  value = object.send(attribute)
  data = { datepicker: "" }
  data[:startdate] = I18n.localize(value, format: :datepicker) if value.present?
  iso_value = value.present? ? value.strftime("%Y-%m-%d") : ""

  template = ""
  template += label(attribute, label_for(attribute) + required_for_attribute(attribute))
  template += @template.text_field(
    @object_name,
    attribute,
    options.merge(name: nil,
                  id: "date_field_#{@object_name}_#{attribute}",
                  data: data)
  )
  template += @template.hidden_field(@object_name, attribute, value: iso_value)
  template += error_and_help_text(attribute, options)
  template.html_safe
end

#datetime_field(attribute, options = {}) ⇒ Object

Public: Generates a timepicker field using foundation datepicker library



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/decidim/form_builder.rb', line 162

def datetime_field(attribute, options = {})
  value = object.send(attribute)
  if value
    iso_value = value.strftime("%Y-%m-%dT%H:%M:%S")
    formatted_value = I18n.localize(value, format: :timepicker)
  end
  template = ""
  template += label(attribute, label_for(attribute) + required_for_attribute(attribute))
  template += @template.text_field(
    @object_name,
    attribute,
    options.merge(value: formatted_value,
                  name: nil,
                  id: "datetime_field_#{@object_name}_#{attribute}",
                  data: { datepicker: "", timepicker: "" })
  )
  template += @template.hidden_field(@object_name, attribute, value: iso_value)
  template += error_and_help_text(attribute, options)
  template.html_safe
end

#editor(name, options = {}) ⇒ Object

Public: generates a hidden field and a container for WYSIWYG editor

name - The name of the field options - The set of options to send to the field

:label   - The Boolean value to create or not the input label (optional) (default: true)
:toolbar - The String value to configure WYSIWYG toolbar. It should be 'basic' or
           or 'full' (optional) (default: 'basic')
:lines   - The Integer to indicate how many lines should editor have (optional) (default: 10)

Renders a container with both hidden field and editor container



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/decidim/form_builder.rb', line 86

def editor(name, options = {})
  options[:toolbar] ||= "basic"
  options[:lines] ||= 10

  (:div, class: "editor") do
    template = ""
    template += label(name, options[:label].to_s || name) if options[:label] != false
    template += hidden_field(name, options)
    template += (:div, nil, class: "editor-container", data: {
                              toolbar: options[:toolbar]
                            }, style: "height: #{options[:lines]}rem")
    template += error_for(name, options) if error?(name)
    template.html_safe
  end
end

#translated(type, name, options = {}) ⇒ Object

Public: Generates an form field for each locale.

type - The form field’s type, like ‘text_area` or `text_input` name - The name of the field options - The set of options to send to the field

Renders form fields for each locale.



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
# File 'lib/decidim/form_builder.rb', line 36

def translated(type, name, options = {})
  if locales.count == 1
    return send(
      type,
      "#{name}_#{locales.first.to_s.gsub("-", "__")}",
      options.merge(label: options[:label] || label_for(name))
    )
  end

  label_tabs = (:div, class: "label--tabs") do
    field_label = label_i18n(name, options[:label] || label_for(name))

    tabs_panels = "".html_safe
    if options[:label] != false
      tabs_panels = (:ul, class: "tabs tabs--lang", id: "#{@object_name}-#{name}-tabs", data: { tabs: true }) do
        locales.each_with_index.inject("".html_safe) do |string, (locale, index)|
          string + (:li, class: tab_element_class_for("title", index)) do
            title = I18n.with_locale(locale) { I18n.t("name", scope: "locale") }
            element_class = nil
            element_class = "is-tab-error" if error?(name_with_locale(name, locale))
            (:a, title, href: "##{name}-panel-#{index}", class: element_class)
          end
        end
      end
    end

    safe_join [field_label, tabs_panels]
  end

  tabs_content = (:div, class: "tabs-content", data: { tabs_content: "#{@object_name}-#{name}-tabs" }) do
    locales.each_with_index.inject("".html_safe) do |string, (locale, index)|
      string + (:div, class: tab_element_class_for("panel", index), id: "#{name}-panel-#{index}") do
        send(type, name_with_locale(name, locale), options.merge(label: false))
      end
    end
  end

  safe_join [label_tabs, tabs_content]
end

#upload(attribute, options = {}) ⇒ Object

Public: Generates a file upload field and sets the form as multipart. If the file is an image it displays the default image if present or the current one. By default it also generates a checkbox to delete the file. This checkbox can be hidden if ‘options` is passed as `false`.

attribute - The String name of the attribute to buidl the field. options - A Hash with options to build the field.

* optional: Whether the file can be optional or not.


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/decidim/form_builder.rb', line 191

def upload(attribute, options = {})
  self.multipart = true
  options[:optional] = options[:optional].nil? ? true : options[:optional]

  file = object.send attribute
  template = ""
  template += label(attribute, label_for(attribute) + required_for_attribute(attribute))
  template += @template.file_field @object_name, attribute

  if file_is_image?(file)
    template += if file.present?
                  @template.label_tag I18n.t("current_image", scope: "decidim.forms")
                else
                  @template.label_tag I18n.t("default_image", scope: "decidim.forms")
                end
    template += @template.link_to @template.image_tag(file.url), file.url, target: "_blank"
  elsif file_is_present?(file)
    template += @template.label_tag I18n.t("current_file", scope: "decidim.forms")
    template += @template.link_to file.file.filename, file.url, target: "_blank"
  end

  if file_is_present?(file)
    if options[:optional]
      template +=  :div, class: "field" do
        safe_join([
                    @template.check_box(@object_name, "remove_#{attribute}"),
                    label("remove_#{attribute}", label_for("remove_#{attribute}"))
                  ])
      end
    end
  end

  template.html_safe
end