Skip to content
Sergio Cambra edited this page Jun 11, 2024 · 22 revisions

If you want to customize the form interface for a column, you have two choices. You can define a specially named partial, or you can define a specially named method in your helper file. The difference between the partial and the helper method is that the partial will be responsible for displaying the label and everything, whereas the helper will only be responsible for displaying the input element (or other interface).

These overrides can be used to hide fields on the form, or even to replace standard inputs with javascript-enabled inputs.

These overrides are currently used by Create and Update.

Helper Override

The helper override is only responsible for display the input element (or whatever else you want). It should be named #{class_name}_#{column_name}_form_column or #{column_name}_form_column. If you want the post to be handled by ActiveScaffold, you need to use the params[:record] namespace. With the helper override this is taken care of if you use the second argument, the options hash. See the example below for more details. Later name will override columns from all models (unless you use clear_helpers method in ApplicationController) or if you put it in ApplicationHelper.

In v2.3 and previous versions format was only #{column_name}_form_column.

Note that with even with subforms, helper overrides only apply to the current controller.

We were able to patch date_select, time_select, and datetime_select to support a :name parameter. With the other set of methods (select_date, select_time, select_datetime) you must use the :prefix parameter instead. See the example below.

Example:

module UsersHelper
  # display the "is_admin" field as a checkbox instead of a dropdown
  def user_is_admin_form_column(record, options)
    check_box :record, :is_admin, options
  end

  def user_birthday_form_column(record, options)
    # with date_select we can use :name
    date_select :record, :birthday, options
    # but if we used select_date we would have to use :prefix
    #select_date record[:birthday], options.merge(:prefix => options[:name])
  end
end

The second argument (options hash) contains the current record in :object key. Also contains the HTML id, class and name attributes generated by ActiveScaffold for the form element. You will need to use these if you generate the HTML directly rather than using Rails form helpers. For example, options could be

{:name=>"record[member][1304426504155][work_location]", :class=>"work_location-input",
 :id=>"record_work_location_1206_member_1304426504155"}

So if you wanted to use your own <select> tag, you could write

my_select = "<select id='#{options[:id]}', name='#{options[:name]}', class='#{options[:class]}'>" +
            ... your selection options ... +
            "</select>"

Previously to v2.3 the second argument was only the input name attribute instead of a full options hash. See example below:

module UsersHelper
  # display the "is_admin" field as a checkbox instead of a dropdown, in v2.3 there is no class name prefix
  def is_admin_form_column(record, input_name)
    check_box :record, :is_admin, :name => input_name
  end

If the association is defined in a STI model, prefixing with the base class is supported too, so subclasses can use a helper override prefixed with own class name, which is specific for the subclass, or share a helper override with the base class name prefix. For example:

class User < ApplicationRecord
end

class Admin < User
end

class Member < User
end

Admin will look for admin_birthday_form_column and user_birthday_form_column, and Member will look for member_birthday_form_column and user_birthday_form_column, so user_birthday_form_column can be defined to use the same field in both models. This is more useful when clear_helpers is not called in ApplicationController, or when the method is defined in ApplicationHelper or any other shared Helper module.

Partial Override (overriding the form element and the label)

The partial override is responsible for displaying the field label, element, description, etc.. It should be named _#{column_name}_form_column.html.erb and be placed in your controller’s views folder.

Example:

app/views/roles/_description_form_column.html.erb

<label>Description</label>
<%= text_area :record, :description, :cols => 25, :rows => 10 %>

Partial gets some local variables, column, only_value, scope, col_class, record. Sometimes you may wish to access the active scaffold configuration in your partial override. By default, the current column is sent in the variable column (API: Column). The column variable has 3 important attributes: column.name, column.label, and column.description. You can access configuration of other columns by using active_scaffold_config.columns[:column_name].

only_value indicates if record shouldn’t be editable, scope is needed for overrides in subforms, col_class are HTML classes added usually in dl tag, usually in subgrops inside subforms.

app/views/roles/_city_form_column.html.erb

<% scope ||= nil %>
<dl>
  <dt>
    <label for="<%= "record_#{column.name}" %>">
      <%= column.label %>, 
      <%= active_scaffold_config.columns[:state].label %>
      <%= active_scaffold_config.columns[:zip].label %>
    </label>
  </dt>
  <dd>
    <% if only value %>
    <% "#{record.city}, #{record.state} #{record.zip}" %>
    <% else %>
    <%= active_scaffold_input_for column, scope, :object => record %>, 
    <%= active_scaffold_input_for active_scaffold_config.columns[:state], scope, :object => record %> 
    <%= active_scaffold_input_for active_scaffold_config.columns[:zip], scope, :object => record %>
  </dd>
</dl>

In this example, state and zip columns should be added to city column’s params:

conf.columns[:city].params.add :state, :zip

Adding html classes which changes on render field action

css_class column’s attribute can be used to add classes to field and li tag, but class cannot be changed when field is rendered again because some other field was changed. If you want to add some attributes to dl tag, which can change everytime field is updated, you can override field_attributes method. This method accepts two arguments: the column and the entire record object, and must return a hash with html attributes, as used in rails helpers.

module UsersHelper
  def field_attributes(column, record)
    if column.name == :ring_2 && record.ring_type != 'ring1&2'
      {:style => "display: none;"}
    else
      super
    end
  end
end
Clone this wiki locally