Class: Vogue::FormBuilder
- Inherits:
-
ActionView::Helpers::FormBuilder
- Object
- ActionView::Helpers::FormBuilder
- Vogue::FormBuilder
- Defined in:
- lib/vogue/form_builder.rb
Overview
The Vogue FormBuilder adds a few handy methods for working with related data. Make your own FormBuilders inherit from this to gain all the Voguey goodness.
Instance Method Summary collapse
-
#check_box_array(method, options = {}, &contents) ⇒ Object
Displays a list of checkboxes which can be ticked.
-
#field_array_controls ⇒ Object
Handy if you want to put the controls for the field array somewhere other than the default.
-
#field_array_for(method, options = {}, &standard_field) ⇒ Object
Presents an extendable array of fields for a has_many relationship on a model.
-
#select_field(method = nil, options = {}) ⇒ Object
Pulls in selection options from methods defined on Dropdowns, the :from option defines the method name to use.
Instance Method Details
#check_box_array(method, options = {}, &contents) ⇒ Object
Displays a list of checkboxes which can be ticked. #method must return an array. Check box items will display the name (or to_s) value of each element obtained by the :from option, of is a block is given, will yield to the block for custom rendering.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/vogue/form_builder.rb', line 106 def check_box_array(method, = {}, &contents) data = .delete(:from) data = drop_down(data, ) if data.is_a?(Symbol) columns = .delete(:columns) || 1 output = ["<table style='width: 100%; border: 0; border-collapse: collapse'>"] output << "<tr>" value = object.send(method) Array(data).each_with_index do |data_item, index| if index % columns == 0 && index > 0 output << "</tr><tr>" end output << "<td>" output << @template.check_box_tag("#{@object_name}[#{method}][]", data_item.id, value.include?(id_value)) output << " " + @template.capture(data_item, &contents) output << "</td>" end output << "</tr></table>" @template.concat output.join end |
#field_array_controls ⇒ Object
Handy if you want to put the controls for the field array somewhere other than the default.
For Example: <% form.field_array_for :tasks do |task| %>
<%= task.field_array_controls %>
<%= task.text_field :name %>
<% end %>
215 216 217 |
# File 'lib/vogue/form_builder.rb', line 215 def field_array_controls "__controls__" end |
#field_array_for(method, options = {}, &standard_field) ⇒ Object
Presents an extendable array of fields for a has_many relationship on a model. The model must have accepts_nested_attributes_for defined on the relationship. Use this as you would use #fields_for, but the block within will be rendered many times.
For Example: <% form.field_array_for :tasks do |task| %>
Name: <%= task.text_field :name %><br/>
Priority: <%= task.select_field :priority, :from => :priorities %>
<% end %>
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/vogue/form_builder.rb', line 140 def field_array_for(method, = {}, &standard_field) method_id = "#{@object_name}_#{method}" template_id = method_id + "_template" array_id = method_id + "_array" list_id = method_id + "_instance" max_size = .delete(:max_size) container_tag = .delete(:container_tag) || "div" row_tag = .delete(:row_tag) || "div" controls_tag = .delete(:controls_tag) || "span" # Build the add and remove buttons. adder = lambda do |show| style = { :class => "field-array-add" } style[:style] = "display: none" unless show @template.link_to_function(@template.image_tag("actions/add.png", :class => "icon"), "#{list_id}.add(this)", style) end remover = @template.link_to_function(@template.image_tag("actions/delete.png", :class => "icon remove"), "#{list_id}.remove(this)") standard_controls = lambda { |show_add| @template.content_tag(controls_tag, remover + adder.call(show_add)) } # Make a list of all the current values, with their remove link and hidden add link. output = [] fields_for(method) do |form| contents = template.capture(form, &standard_field) contents += form.hidden_field(:_destroy, :class => "deletion_marker") unless form.object.new_record? if contents.include?("__controls__") contents.sub!("__controls__", standard_controls.call(false)) else contents += " " + standard_controls.call(false) end output << @template.content_tag(row_tag, contents, :class => "element") end new_object = object.class.reflect_on_association(method).klass.new new_contents = nil Rails.logger.debug("[DashFormBuilder] Generating fields for blank records...") fields_for(method, new_object, :child_index => "NEW_RECORD") do |form| new_contents = @template.capture(form, &standard_field) if new_contents.include?("__controls__") new_contents.sub!("__controls__", standard_controls.call(false)) else new_contents += " " + standard_controls.call(false) end end template = @template.content_tag(row_tag, new_contents, :class => "element") blank_entry = @template.escape_javascript(template) 0.upto(max_size || 0) do output << template.gsub(/NEW_RECORD/, Time.now.to_i.to_s) end Rails.logger.debug("[DashFormBuilder] Rendering output...") render_output = @template.javascript_tag("var #{list_id} = null;") + \ @template.content_tag(container_tag, output.to_s, :id => array_id, :class => "text_field_array") + \ @template.javascript_tag("#{list_id} = new DashList('#{array_id}', '#{blank_entry}'#{max_size.blank? ? '' : ',' + max_size.to_s});") @template.concat render_output end |
#select_field(method = nil, options = {}) ⇒ Object
Pulls in selection options from methods defined on Dropdowns, the :from option defines the method name to use. In addition to the from option, many other options are supported which can enhance the functionality of the select field generated.
:value_method => The method to use on the data source to obtain the value that should be returned to the server. :text_method => The method to use on the data source to obtain the display text that should be displayed to the user. :from => If a symbol, it calls the relevant method on IProperty::Render::Dropdowns, otherwise it accepts an array. :include_blank => A blank option will be included at the top of the list displaying the assigned string. :include_create => The assigned text will be displayed at the bottom of the list allowing the creation of a new value. This new value is returned to the server. :create_width => How wide the creation text box should be (defaults to 20em). :include_current => Includes the currently selected option at the top of the list. If a string, displays the string, replacing “~” with the current display text.
16 17 18 19 20 21 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 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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/vogue/form_builder.rb', line 16 def select_field(method = nil, = {}) source = .delete(:from) extra_html = [] = Hash.new id_method = .delete(:value_method) || "id" text_method = .delete(:text_method) || "name" value = object.try(method) selections = nil data = if source.is_a?(Symbol) drop_down(source, ) elsif source.is_a?(Array) source else # Attempt to infer from the field name. if reflection = object.class.reflect_on_association(method.to_sym) drop_down(reflection.class_name.tableize, ) else raise "from must be either a symbol or an array" end end # Check to see if the data is in a grouped format. That is, we're getting [["Group Name", [data...]], ["Another Group", [data...]]]. selections = if data.first.is_a?(Array) && data.first.last.is_a?(Array) # Check to see if the grouped data has already been converted into an array (instead of a list of domain objects). if data.first.last.first.is_a?(Array) id_method = :last text_method = :first end template.option_groups_from_collection_for_select(data, :last, :first, id_method, text_method, value) else # Check to see if its de-normalized (i.e, we're receiving data like this: [["Name", "Value"], ["Name", "Value"]]) if data.first.is_a?(Array) id_method = :last text_method = :first elsif !data.first.is_a?(ActiveRecord::Base) id_method = :to_s text_method = :to_s value = value.to_s end template.(data, id_method, text_method, value) end if [:include_blank] selections = template.content_tag(:option, [:include_blank].is_a?(String) ? [:include_blank] : nil, :value => "") + selections end if [:include_create] working_with_new_value = !value.blank? && !selections.any? { |a| a.last.to_s == value.to_s } selections = selections + template.content_tag(:option, [:include_create], :value => "-new-") if !value.blank? && [:include_current] selections = template.content_tag(:option, [:include_current].sub("~", value.send(text_method)), :value => value.send(id_method)) + selections working_with_new_value = false end width = [:create_width] || "20em" result = [] if working_with_new_value extra_html << template.tag(:input, :type => "text", :id => "#{@object_name}_#{method}_new_input", :name => "#{@object_name}[#{method}]", :style => "width: #{width}", :value => value) else [:onchange] = "if($F(this) == '-new-') { $('#{@object_name}_#{method}_new').show(); $('#{@object_name}_#{method}').hide(); $('#{@object_name}_#{method}').writeAttribute('disabled', true); $('#{@object_name}_#{method}_new_input').writeAttribute('disabled', false); }" input = template.tag(:input, :type => "text", :id => "#{@object_name}_#{method}_new_input", :name => "#{@object_name}[#{method}]", :style => "width: #{width}", :disabled => "disabled") extra_html << template.content_tag(:div, input, :id => "#{@object_name}_#{method}_new", :style => "display: none") end result.join else if !value.blank? && [:include_current] selections = @template.content_tag(:option, [:include_current].sub("~", value), :value => value) + selections end end [:onclick] = .delete(:onclick) if [:onclick] [:class] = .delete(:class) if [:class] [:style] = .delete(:style) if [:style] template.select_tag("#{@object_name}[#{method}]", selections, ) + " " + extra_html.join end |