Extending forms

One of the Ruby's best properties is availability to dynamically extend already defined modules and classes. This so-called monkey patching can be sometimes very dangerous, but if used with caution, it may lead to wonderful solutions. DRGCMS forms may be extended simply by adding classes to DrgCmsFomField module.

 

Default fields used in DRG CMS forms are defined in drgcms_form_fields.rb file. Source file defines DrgCmsFormFields module. Inside this module, form field classes are defined. One class for each type used in form field declaration. Select class for select field type, MultitextAutocomplete for multitext_autocomplete field type etc... Let's look how datetime_picker field is defined.

 

module DrgcmsFormFields
class DatetimePicker < DrgcmsField

def render
  # return value with ro_standard method
  return ro_standard if @readonly

  # prepare for initialization. set_initial_value will prepare initial value for field when
  # field is initialized through url parameters (p_name parameter).
  @yaml['options'] ||= {}
  set_initial_value

  # default html options
  @yaml['html']['size'] ||= 12
  @yaml['html']['value'] = I18n.localize(@record[@yaml['name']].localtime) if @record[@yaml['name']]

  # default field javascript options
  @yaml['options']['lang']   ||= "'#{I18n.locale}'"
  @yaml['options']['format'] ||= "'#{t('datetimepicker.formats.datetime')}'"

  # presentation is simple text_field with some javascript added
  @html << @parent.text_field('record', @yaml['name'], @yaml['html'])

  @js << <<EOJS
$(document).ready(function() {
$("#record_#{@yaml['name']}").datetimepicker( {
  #{hash_to_options(@yaml['options'])}
});
});
EOJS

  # must return self 
  self
end

###########################################################################
# get_data returns value which will be saved to document from form field.
# Data is extracted from params['record'][field_name] parameter.
###########################################################################
def self.get_data(params, name)
  t = params['record'][name].to_datetime
  t ? Time.zone.renderlocal(t.year, t.month, t.day, t.hour, t.min) : nil
end

end
end

 

Our class inherits from DrgcmsField abstract class, which also holds some common code useful for all form fields. It has render method which examines parameters and options defined in form and prepares HTML and JS code in @html and @js instance variables. This code is at the end scoped by form creation helper.

 

Class must also define class method self.get_data which is used by cmsedit controller to extract data entered in browser and will be saved to document.

 

drg_default_html_editor gem is an example of how DRG Form files can be extended and packed as ruby gem.

 

Extend DRG Form fields

 

You may add additional DRG Form fields only for the current project. Create my_field.rb in the app/models (pick your own name) directory, and start with these lines.

 

module DrgcmsFormField # the new class goes into DrgcmsFormField module

class MyField < DrgcmsField # define new class and inherit from DrgcmsField

def render
  p @yaml['type'] # => my_field; @yaml holds form definition for this field
  p @record[@yaml['name']] # => 'whatever'; @record holds value of field on document
  @html << html_code
  @js << javascript_code
end

def self.get_data(params, name)
  value_to_be_saved_to_document
end

end
end

Last update: 26.01.2022