Class: Netzke::Basepack::GridPanel
- Inherits:
-
Netzke::Base
- Object
- Netzke::Base
- Netzke::Basepack::GridPanel
- Extended by:
- ActiveSupport::Memoizable
- Includes:
- DataAccessor, selfself::Columns, selfself::Services
- Defined in:
- lib/netzke/basepack/grid_panel.rb,
lib/netzke/basepack/grid_panel/columns.rb,
lib/netzke/basepack/grid_panel/services.rb,
lib/netzke/basepack/grid_panel/record_form_window.rb
Overview
Ext.grid.EditorGridPanel-based component with the following features:
-
ActiveRecord-model support with automatic column configuration
-
multi-line CRUD operations - get, post, delete, create
-
(multe-record) editing and adding records through a form
-
persistent column resize, move and hide
-
permissions
-
sorting
-
pagination
-
filtering
-
advanced search
-
rows reordering by drag-n-drop, requires acts_as_list on the model
-
virtual attribute support
-
(TODO) dynamic configuration of properties and columns
Instance configuration
The following config options are supported:
-
model
- name of the ActiveRecord model that provides data to this GridPanel, e.g. “User” -
columns
- an array of columns to be displayed in the grid; each column may be represented by a symbol (representing the model’s attribute name), or a hash (when extra configuration is needed). See the “Columns” section below. -
scope
- specifies how the data should be filtered. When it’s a symbol, it’s used as a scope name. When it’s a string, it’s a SQL statement (passed directly towhere
). When it’s a hash, it’s a conditions hash (passed directly towhere
). When it’s an array, it’s expanded into an SQL statement with arguments (passed directly towhere
), e.g.::scope => ["id > ?", 100])
When it’s a Proc, it’s passed the model class, and is expected to return a ActiveRecord::Relation, e.g.:
:scope => { |rel| rel.where(:id.gt => 100).order(:created_at) }
-
strong_default_attrs
- (defaults to {}) a hash of attributes to be merged atop of every created/updated record, e.g. => 1 -
enable_column_filters
- (defaults to true) enable filters in column’s context menu -
enable_edit_in_form
- (defaults to true) provide buttons into the toolbar that activate editing/adding records via a form -
enable_extended_search
- (defaults to true) provide a button into the toolbar that shows configurable search form -
enable_context_menu
- (defaults to true) enable rows context menu -
context_menu
- an array of actions (e.g. [:edit.action, “-”, :del.action] - see the Actions section) orfalse
to disable the context menu -
enable_rows_reordering
- (defaults to false) enable reordering of rows with drag-n-drop; underlying model (specified inmodel
) must implement “acts_as_list”-compatible functionality -
enable_pagination
- (defaults to true) enable pagination -
rows_per_page
- (defaults to 30) number of rows per page (ignored whenenable_pagination
is set tofalse
) -
load_inline_data
- (defaults to true) load initial data into the grid right after its instantiation -
(TODO)
mode
- when set toconfig
, GridPanel loads in configuration mode -
[add|edit|multi_edit]_search_form_config
- additional configuration for add/edit/multi_edit/search form panel -
[add|edit|multi_edit]_form_window_config
- additional configuration for the window that wrapps up add/edit/multi_edit form panel
Columns
Columns are configured by passing an array to the columns
option. Each element in the array is either the name of model’s (virtual) attribute (in which case the configuration will be fully automatic), or a hash that may contain the following configuration options as keys:
-
name
- (required) name of the column, that may correspond to the model’s (virtual) attribute -
read_only
- a boolean that defines if the cells in the column should be editable -
editable
- same asread_only
, but in reverse (takes precedence overread_only
) -
filterable
- set to false to disable filtering on this column -
getter
- a lambda that receives a record as a parameter, and is expected to return a string that will be sent to the cell (can be HTML code), e.g.::getter => lambda {|r| [r.first_name, r.last_name].join }
-
setter
- a lambda that receives a record as first parameter, and the value passed from the cell as the second parameter, and is expected to modify the record accordingly, e.g.::setter => lambda { |r,v| r.first_name, r.last_name = v.split(" ") }
-
scope
- the scope for one-to-many association column. Same syntax applies as for scoping out records for the grid itself. See “One-to-many association support” for details. -
sorting_scope
- the name of the scope used for sorting the column. This can be useful for virtual columns for example. The scope will get one parameter specifying the direction (:asc or :desc). Example:columns => [{ :name => "complete_user_name", :sorting_scope => :sort_user_by_full_name }, ...] class User < ActiveRecord::Base scope :sort_user_by_full_name, lambda { |dir| order("users.first_name #{dir.to_s}, users.last_name #{dir.to_s}") } end
-
format
- the format to display data in case of date and datetime columns, e.g. ‘Y-m-d g:i:s’.
Besides these options, a column can receive any meaningful config option understood by Ext.grid.column.Column.
One-to-many association support
If the model bound to a grid belongs_to
another model, GridPanel can display an “assocition column” - where the user can select the associated record from a drop-down box. You can specify which method of the association should be used as the display value for the drop-down box options by using the double-underscore notation on the column name, where the association name is separated from the association method by “__” (double underscore). For example, let’s say we have a Book that belongs_to
model Author, and Author responds to first_name
. This way, the book grid can have a column defined as follows:
{:name => "author__first_name"}
GridPanel will detect it to be an association column, and will use the drop-down box for selecting an author, where the list of authors will be represented by the author’s first name.
In order to scope out the records displayed in the drop-down box, the scope
column option can be used, e.g.:
{:name => "author__first_name", :scope => lambda{|relation| relation.where(:popular => true)}}
Add/edit/search forms
The forms will by default display the fields that correspond to the configured columns, taking over meaningful configuration options (e.g. text
will be converted into fieldLabel
). You may override the default fields displayed in the forms by overriding the default_fields_for_forms
method, which should return an array understood by the items
config property of the FormPanel
. If you need to use a custom class instead of FormPanel
, you may need to go an extra mile overriding the corresponding GridPanel’s child component (e.g. “add_form” or “edit_form”).
Actions
You can override GridPanel’s actions to change their text, icons, and tooltips (see api.netzke.org/core/Netzke/Actions.html).
GridPanel implements the following actions:
-
add
- inline adding of a record -
del
- deletion of records -
edit
- inline editing of a record -
apply
- applying inline changes -
add_in_form
- adding a record in a form -
edit_in_form
- (multi-record) editing in a forrm -
search
- advanced searching
Class configuration
Configuration on this level is effective during the life-time of the application. One place for setting these options are in application.rb, e.g.:
config.netzke.basepack.grid_panel.column_filters_available = false
These can also be eventually set directly on the component’s class:
Netzke::Basepack::GridPanel.column_filters_available = false
Most of these options influence the amount of JavaScript code that is generated for this component’s class, in the way that the less functionality is enabled, the less code is generated.
The following class configuration options are available:
-
column_filters_available
- (defaults to true) include code for the filters in the column’s context menu -
(TODO)
config_tool_available
- (defaults to true) include code for the configuration tool that launches the configuration panel -
edit_in_form_available
- (defaults to true) include code for (multi-record) editing and adding records through a form -
extended_search_available
- (defaults to true) include code for extended configurable search
Defined Under Namespace
Modules: Columns, Services Classes: RecordFormWindow
Class Method Summary collapse
-
.inherited(base) ⇒ Object
Inject some handy DSL methods into the child classes.
Instance Method Summary collapse
- #configuration ⇒ Object
-
#default_bbar ⇒ Object
Override to change the default bottom toolbar.
-
#default_context_menu ⇒ Object
Override to change the default context menu.
-
#get_association_values(record) ⇒ Object
:nodoc:.
-
#get_default_association_values ⇒ Object
:nodoc:.
-
#js_config ⇒ Object
:nodoc:.
Methods included from DataAccessor
#association_attr?, #combobox_options_for_column, #data_adapter, #data_class, #normalize_attr, #normalize_attrs, #primary_key_attr?, #set_default_virtual
Class Method Details
.inherited(base) ⇒ Object
Inject some handy DSL methods into the child classes.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/netzke/basepack/grid_panel.rb', line 200 def self.inherited(base) super base.class_eval do class << self def column(name, config = {}) columns = self.columns_attr || [] columns |= [config.merge(:name => name.to_s)] self.columns_attr = columns end def override_column(name, config) columns = self.overridden_columns_attr.dup self.overridden_columns_attr = columns.merge(name.to_sym => config) end end end end |
Instance Method Details
#configuration ⇒ Object
219 220 221 222 223 224 225 226 |
# File 'lib/netzke/basepack/grid_panel.rb', line 219 def configuration super.tap do |c| c[:columns] ||= self.columns_attr # user-passed :override_columns option should get deep_merged with the defaults c[:override_columns] = self.overridden_columns_attr.deep_merge(c[:override_columns] || {}) end end |
#default_bbar ⇒ Object
Override to change the default bottom toolbar
260 261 262 263 264 265 |
# File 'lib/netzke/basepack/grid_panel.rb', line 260 def res = %w{ add edit apply del }.map(&:to_sym).map(&:action) res << "-" << :add_in_form.action << :edit_in_form.action if config[:enable_edit_in_form] res << "-" << :search.action if config[:enable_extended_search] res end |
#default_context_menu ⇒ Object
Override to change the default context menu
268 269 270 271 272 |
# File 'lib/netzke/basepack/grid_panel.rb', line 268 def res = %w{ edit del }.map(&:to_sym).map(&:action) res << "-" << :edit_in_form.action if config[:enable_edit_in_form] res end |
#get_association_values(record) ⇒ Object
:nodoc:
242 243 244 245 246 |
# File 'lib/netzke/basepack/grid_panel.rb', line 242 def get_association_values(record) #:nodoc: columns.select{ |c| c[:name].index("__") }.each.inject({}) do |r,c| r.merge(c[:name] => record.value_for_attribute(c, true)) end end |
#get_default_association_values ⇒ Object
:nodoc:
248 249 250 251 252 253 254 255 256 |
# File 'lib/netzke/basepack/grid_panel.rb', line 248 def get_default_association_values #:nodoc: columns.select{ |c| c[:name].index("__") && c[:default_value] }.each.inject({}) do |r,c| assoc_name, assoc_method = c[:name].split '__' assoc_class = data_adapter.class_for(assoc_name) assoc_data_adapter = Netzke::Basepack::DataAdapters::AbstractAdapter.adapter_class(assoc_class).new(assoc_class) assoc_instance = assoc_data_adapter.find_record c[:default_value] r.merge(c[:name] => assoc_instance.send(assoc_method)) end end |
#js_config ⇒ Object
:nodoc:
228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/netzke/basepack/grid_panel.rb', line 228 def js_config #:nodoc: res = super res.merge({ :title => res[:title] || self.class.js_properties[:title] || data_class.name.pluralize, :bbar => config.has_key?(:bbar) ? config[:bbar] : , :context_menu => config.has_key?(:context_menu) ? config[:context_menu] : , :columns => columns(:with_meta => true), # columns :columns_order => columns_order, :model => config[:model], # the model name :inline_data => (get_data if config[:load_inline_data]), # inline data (loaded along with the grid panel) :pri => data_class.primary_key # table primary key name }) end |