module ExtForm module Builders class FormBuilderBase < SimpleForm::FormBuilder # include nested_form include ::NestedForm::BuilderMixin attr_accessor :l, :input_seq, :before_row_start_callbacks, :after_row_start_callbacks, :before_row_end_callbacks, :after_row_end_callbacks map_type :date_picker, :time_picker, :dt_picker, to: ExtForm::Inputs::DtPicker map_type :auto_complete, to: ExtForm::Inputs::AutoComplete map_type :select, to: ExtForm::Inputs::CollectionSelect map_type :grouped_select, to: ExtForm::Inputs::GroupedCollectionSelect map_type :original_select, to: SimpleForm::Inputs::CollectionSelectInput map_type :original_grouped_select, to: SimpleForm::Inputs::GroupedCollectionSelectInput def initialize(*) super self.input_seq = 0 self.l = ['ExtForm','Layouts', ExtForm.layout].join('::').constantize.new l.setup_config(options[:l]) self.before_row_start_callbacks = [] self.after_row_start_callbacks = [] self.before_row_end_callbacks = [] self.after_row_end_callbacks = [] end # Public: Wrapper for using ExtForm inside a ext rails form. # Example: # # ext_form_for @user do |f| # f.ext_fields_for :posts do |posts_form| # # Here you have all simple_form methods available # posts_form.input :title # end # end def ext_fields_for(record_name, record_object = nil, options = {}, &block) record_object, options = nil, record_object if record_object.is_a?(Hash) options[:wrapper] ||= self.options[:wrapper] options[:defaults] ||= self.options[:defaults] options[:l] ||= self.options[:l] if self.class < ActionView::Helpers::FormBuilder options[:builder] ||= self.class else options[:builder] ||= ExtForm::Builders::FormBuilder end simple_fields_for(record_name, record_object, options, &block) end def inputs(*args, &block) if args.first.is_a?(String) && args.first.match(/^\d+(:?\d?)?$/) layout = args.shift attributes = args else layout, attributes = nil, args end if layout.blank? self.input_seq = 0 output = [] attributes.each do |a| if find_attribute_column(a) output << input(a) elsif find_association_reflection(a) output << association(a) else raise 'Attribute must be a column or an association of this model.' end end output << @template.capture(self, &block) if block_given? output << all_row_end.try(:html_safe) output.compact.join.html_safe else swap_layout(layout, attributes, &block) end end def input(attribute_name, options={}, &block) options[:input_seq] = self.input_seq output = [] output << row_start output << super(attribute_name, options, &block) output << row_end self.input_seq += 1 output.compact.join.html_safe end def before_row_start(&block) before_row_start_callbacks << block '' end def before_row_end(&block) before_row_end_callbacks << block '' end def after_row_start(&block) after_row_start_callbacks << block '' end def after_row_end(&block) after_row_end_callbacks << block '' end def dt_picker(method, options={}) default_data_options = { format: 'yyyy-MM-dd hh:mm:ss', language: ExtForm.locale } options[:data] ||= {} options[:data].reverse_merge!(default_data_options) @template.dt_picker(@object_name, method, objectify_options(options)) end def date_picker(method, options={}) fixed_data_options = { pick_time: false } default_data_options = { format: 'yyyy-MM-dd', language: ExtForm.locale } options[:data] ||= {} options[:data].merge!(fixed_data_options).reverse_merge!(default_data_options) @template.dt_picker(@object_name, method, objectify_options(options)) end def time_picker(method, options={}) fixed_data_options = { pick_date: false } default_data_options = { format: 'hh:mm:ss', language: ExtForm.locale } options[:data] ||= {} options[:data].merge!(fixed_data_options).reverse_merge!(default_data_options) @template.dt_picker(@object_name, method, objectify_options(options)) end def auto_complete(method, options={}) @template.auto_complete(@object_name, method, objectify_options(options)) end def collection_select2(method, collection, value_method, label_method, options={}, html_options={}) @template.collection_select2(@object_name, method, collection, value_method, label_method, objectify_options(options), html_options) end def grouped_collection_select2(method, grouped_collection, group_method, group_label_method, value_method, label_method, options={}, html_options={}) @template.collection_select2(@object_name, method, grouped_collection, group_method, group_label_method, value_method, label_method, objectify_options(options), html_options) end private def swap_layout(layout=nil, attributes=[], &block) options = self.options.dup options[:l] = l.layout_config.dup.merge(layout: layout) options[:parent_builder] = nil new_block = proc { |f| f.inputs(*attributes) do block.call(f) if block_given? end } @template.ext_fields_for(object, options, &new_block) end def row_start if input_seq % l.layout.size == 0 output = [] before_row_start_callbacks.each do |c| output << template.capture(&c) end output << '
' after_row_start_callbacks.each do |c| output << template.capture(&c) end output.compact.join end end def row_end generate_row_end if (input_seq + 1) % l.layout.size == 0 end def all_row_end generate_row_end if input_seq % l.layout.size != 0 end def generate_row_end output = [] before_row_end_callbacks.each do |c| output << template.capture(&c) end output << '
' after_row_end_callbacks.each do |c| output << template.capture(&c) end output.compact.join end end end end