Module: NestedFormsHelper
- Defined in:
- app/helpers/nested_forms_helper.rb
Instance Method Summary collapse
-
#button_to_stimulus_nested_form(name, options = {}) ⇒ Object
Stimulus-based nested forms using stimulus-components/rails-nested-form Stimulus-based nested forms — preferred for new code.
- #generate_html(form_builder, method, options = {}) ⇒ Object
-
#link_to_new_nested_form(name, form_builder, method, options = {}, instance_defaults = nil) ⇒ Object
Legacy nested forms (to be migrated to Stimulus).
-
#nested_form_delete_icon(f, selector, label_text = nil, **opts) ⇒ Object
Keyword options (all optional): :icon, :icon_options (passed to fa_icon), :link_class, :title, :aria_label.
Instance Method Details
#button_to_stimulus_nested_form(name, options = {}) ⇒ Object
Stimulus-based nested forms using stimulus-components/rails-nested-form
Stimulus-based nested forms — preferred for new code
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'app/helpers/nested_forms_helper.rb', line 112 def (name, = {}) css_classes = [] if [:class].present? css_classes << [:class] else css_classes += %w[btn btn-outline-primary] end = if block_given? yield elsif [:skip_icon].to_b name else fa_icon('circle-plus', text: name) end # Use the controller name from options or default to 'nested-form' controller_name = [:controller] || 'nested-form' data_hsh = { action: "#{controller_name}#add" }.merge([:data] || {}) .html_safe, id: [:id], type: 'button', class: css_classes.compact.uniq.join(' '), style: [:style], data: data_hsh end |
#generate_html(form_builder, method, options = {}) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 |
# File 'app/helpers/nested_forms_helper.rb', line 4 def generate_html(form_builder, method, = {}) [:object] ||= form_builder.object.class.reflect_on_association(method).klass.new [:partial] ||= method.to_s.singularize [:form_builder_local] ||= :f [:partial_locals] ||= {} child_index = [:child_index] || 'NEW_RECORD' builder_method = form_builder.respond_to?(:simple_fields_for) ? :simple_fields_for : :fields_for form_builder.send(builder_method, method, [:object], child_index: child_index) do |f| render(partial: [:partial], locals: { [:form_builder_local] => f }.merge([:partial_locals])) end end |
#link_to_new_nested_form(name, form_builder, method, options = {}, instance_defaults = nil) ⇒ Object
Legacy nested forms (to be migrated to Stimulus).
Pass use_stimulus_append: true to omit .new-nested-form and use .rma-add-items-nested-trigger
(rma-add-items Stimulus controller). Pass stimulus_nested_trigger_class: 'my-class' for a
page-specific trigger (rma-receive-items, etc.); that controller must handle the click.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'app/helpers/nested_forms_helper.rb', line 60 def link_to_new_nested_form(name, form_builder, method, = {}, instance_defaults = nil) instance_defaults ||= [:defaults] || {} [:object] ||= form_builder.object.class.reflect_on_association(method).klass.new(instance_defaults) [:partial] ||= method.to_s.singularize [:form_builder_local] ||= :f [:element_id] ||= method.to_s [:partial_locals] ||= {} html = generate_html(form_builder, method, object: [:object], partial: [:partial], form_builder_local: [:form_builder_local], partial_locals: [:partial_locals], child_index: [:child_index]) use_stimulus_append = [:use_stimulus_append] stimulus_trigger_class = [:stimulus_nested_trigger_class].to_s.presence css_classes = [] if [:class].present? css_classes << [:class] else css_classes += %w[btn btn-outline-primary] end css_classes << if stimulus_trigger_class stimulus_trigger_class elsif use_stimulus_append 'rma-add-items-nested-trigger' else 'new-nested-form' end link_label = if block_given? yield elsif [:skip_icon].to_b name else fa_icon('circle-plus', text: name) end data_hsh = { 'element-id': [:element_id], partial: h(html.to_s), trigger: [:trigger] }.merge([:data] || {}) link_to link_label.html_safe, '#', id: [:id], class: css_classes.compact.uniq.join(' '), style: [:style], data: data_hsh end |
#nested_form_delete_icon(f, selector, label_text = nil, **opts) ⇒ Object
Keyword options (all optional): :icon, :icon_options (passed to fa_icon), :link_class, :title, :aria_label
Non-persisted branch: +icon_args+ is built from +icon_base+ (+icon_options+ dup). If both +label_text+
and +:text+ in +icon_options+ are present, +label_text+ wins (written into +icon_args[:text]+) and
Rails.logger.warn records the conflict.
22 23 24 25 26 27 28 29 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 |
# File 'app/helpers/nested_forms_helper.rb', line 22 def nested_form_delete_icon(f, selector, label_text = nil, **opts) icon_name = (opts[:icon] || 'trash').to_s icon_base = (opts[:icon_options] || {}).dup extra_link_class = opts[:link_class].presence title = opts[:title] aria_label = opts[:aria_label] if f.object.present? && f.object.persisted? f.label '_destroy', class: 'p-0 m-0' do inner = fa_icon(icon_name, **icon_base) + f.check_box('_destroy') inner += tag.span(label_text, class: 'ms-1') if label_text.present? inner end else icon_args = icon_base.dup if label_text.present? && (icon_args.key?(:text) || icon_args.key?('text')) Rails.logger.warn( '[nested_form_delete_icon] label_text and icon_options[:text] were both set; ' \ "label_text wins and replaces icon_args[:text]. label_text=#{label_text.inspect}, " \ "icon_options=#{opts[:icon_options].inspect}, icon_base keys=#{icon_base.keys.inspect}" ) end if label_text.present? icon_args.delete('text') icon_args[:text] = label_text end link_classes = ['btn', 'trash-remove', 'p-0', 'm-0', extra_link_class].compact.join(' ') link_opts = { class: link_classes, 'data-class-to-remove': selector } link_opts[:title] = title if title.present? link_opts[:'aria-label'] = aria_label if aria_label.present? link_to fa_icon(icon_name, **icon_args), '#', **link_opts end end |