基于Ruby On Rails Extjs Grid的拓展

1.拓展原生Ext GridPanel使其支持后台数据库数据动态构建,所有字段的查询,排序,自定义查询,行编辑器等功能

2.该类Extjs代码:

Ext.QuickTips.init();
Ext.define("Wando.grid.Panel", {
    extend: "Ext.grid.Panel",
    alias: "widget.wandogrid",
    //该配置会自动生成getter setter method
    config: {
        plugin: [],
        features: [],
    },
    split:true,

    //构造自定义render方法
    onRender: function() {
        this.callParent(arguments);
    },

    constructor: function(cfg) {
        this.gridConfig = cfg;
        this.data = this.getColumnData();
        //autoLoad 默认为true
        this.isAutoLoad = cfg.autoLoad == false ? false: true
        this.isSort = cfg.remoteSort == false ? false: true
        var store = this.createStore();
        var rowEditor = this.createRowEditor();
        var features = this.createFilter();
        var config = {
            forceFit: true,
            plugins: this.gridConfig.rowEditor == false ? []:[rowEditor],
            features: [features],
            store: store,
            bbar: Ext.create('Ext.PagingToolbar', {
                store: store,
                displayInfo: true,
                displayMsg: '显示第 {0} - {1} 条记录,共{2}条',
                emptyMsg: "没有记录",
            })
        };
        Ext.apply(this, config);
        this.initConfig(cfg);
        this.callParent(arguments);
        return this;
    },

    //会被构造器调用,用来初始化数据,配置,绑定事件处理
    initComponent: function() {
        this.callParent(arguments);
        this.addPagingButton();
    },

    createStore: function() {
        me = this;
        column = me.data.columns;
        fields = me.data.fields;
        return Ext.create('Wando.data.Store', {
            fields: fields,
            baseParams: {
                columnsConfig: column
            },
            remoteSort:me.isSort,
            proxy: {
                type: 'ajax',
                url: me.gridConfig.url,
                reader: {
                    type: 'json',
                    root: 'result'
                }
            },
            autoLoad: me.isAutoLoad,
        });
    },

    getColumnData: function() {
        var columns = this.gridConfig.columns;
        var columnsConfig = {};
        var fields = [];
        var filters = [];
        Ext.each(columns, function(column) {
            if (!Ext.isEmpty(column.dataIndex)) {
                columnsConfig[column.columnName] = column.dataIndex;
                fields.push(column.dataIndex);
                var type = column.type ? column.type: "string";
                filters.push({
                    dataIndex: column.dataIndex,
                    type: type
                });
            }
        });
        data = {
            columns: Ext.encode(columnsConfig),
            fields: fields,
            filters: filters
        };
        return data;
    },

    createFilter: function() {
        filters = this.data.filters;
        return filters = {
            ftype: 'filters',
            encode: false,
            local: true,
            filters: filters
        };
    },

    createRowEditor: function() {
        return Ext.create('Ext.grid.plugin.RowEditing', {
            clicksToEdit: 2,
            clicksToMoveEditor: 1,
            saveBtnText: '保存/修改',
            cancelBtnText: '取消',
            listeners:{ 
                "afteredit":function(){ 
                    if (this.whenRowSave){ 
                        this.whenRowSave();
                    }
                },
                scope:this
            }
        })
    },


    addPagingButton: function() {
        var me = this;
        this.child('pagingtoolbar').add(['->', {
            text: me.filters.local ? '本地查询': '远程查询',
            //tooltip: '查询本地数据或者所有数据',
            enableToggle: true,
            handler: function(button, state) {
                var local = (me.filters.local !== true),
                  text = local ? '本地查询' : '远程查询',
                  newUrl = me.gridConfig.url,
                  store = me.view.getStore();
                me.filters.local = local;
                me.filters.bindStore(store);
                store.proxy.url = newUrl;
                button.setText(text);
                store.load();
            }
        },
        {
            text: '清除查询',
            scope:this,
            tooltip: '去掉查询条件,显示所有数据',
            handler: function() {
                this.filters.clearFilters();
                this.store.reload();
            }
        },{
            text: '自定义查询',
            scope:this,
            tooltip: '允许用户自定义查询条件',
            handler: function() {
                Wando.msg.info("","功能完善中");
            }
        }])
    },

    getToolbar: function(){ 
        return this.getDockedItems('toolbar[dock="top"]')[0];
    }

});

3.Ruby代码:

# -*- encoding : utf-8 -*-
module WandoGrids 
  # User: Justin 
  # Comment:构造Wando.Grid的后台数据 
  # date: 2013-03-04 
  # params: 前台wando_grid默认传入参数,用于数据查找,考虑不需要传该参数
  # object: 传入你需要获取数据的 object 名字,object.class必须为ActivityRecord
  # options: 传入附加的条件 
  # 返回records的动态表头

  def wando_grid params,object,option ={ }
    order = ""
    if not params[:sort].nil?
      JSON.parse(params[:sort]).each do |k|
        if not object.column_names.include?(k["property"])
          order = 'id' + ' ' + k["direction"].to_s
        else
          order = k["property"].to_s + " " + k["direction"].to_s
        end
      end
    end
    default_options = 
    { 
      :order => params[:order],
      :offset => params[:offeset].to_i,
      :start => params[:start].to_i || 0,
      :limit => params[:limit].to_i || 50
    } 
    fields = []
    column_name = []
    result = []
    relation = JSON.parse(params[:columnsConfig])
    relation.each do |o,e|
      fields<< e 
      column_name << o
    end
    column_name.push("id")
    offset = default_options[:offeset].to_i + default_options[:start].to_i
    records = object.where(option).order(order).limit(params[:limit]).offset(offset).search(buildFilterOptions(object,params[:filter])).result(:distinct => true).provide(*column_name)
    count = object.count
    records.each do |r| 
      result << Hash[r.map {|k, v| [relation[k], v] }]
    end
    render :json => {  
      :success => true,
      :total => count,
      :result => result,
    }
  end

  def get_record_by_fields fields,object,option ={ }
    fields = JSON.parse(fields) unless fields.is_a? Array
    records = object.where(option).provide(*fields)
    render :json => { 
      :success => true,
      :result => records
    }
  end

  def buildFilterOptions(object,filter_hash)
    return { } if filter_hash.nil? 
    fs = { }
    filter_hash = filter_hash.delete_if {|key, value| value.blank? }
    filter_hash.each do |columns, fvals|
      fs_tmp = { }
      relation = JSON.parse(params[:columnsConfig]) 
      gf_field = relation.invert[fvals[:field]].downcase.gsub("/","_")
      gf_type = fvals[:data][:type].downcase
      gf_value = fvals[:data][:value]
      gf_comparison = fvals[:data][:comparison]

      case gf_type
        when 'numeric'
          case gf_comparison
            when 'gt'
              gf_field += "_gt"
            when 'lt'
              gf_field += "_lt"
            when 'eq'
              gf_field += "_eq"
            when 'ne'
              gf_field += "_neq"
          end
          fs_tmp[gf_field.to_sym] = gf_value.to_i
        when 'string'
          gf_field += "_cont"
          fs_tmp[gf_field.to_sym] = gf_value.to_s
        when 'boolean'
          gf_value = gf_value.downcase
          if gf_value == 'true' or gf_value == 'false'
            gf_field += "_" + gf_value
            fs_tmp[gf_field.to_sym] = "1"
          end
        when 'list'
          gf_field += "_cont"
          fs_tmp[gf_field.to_sym] = gf_value.to_s
        when 'date'
          case gf_comparison
            when 'gt'
              gf_field += '_gt'
            when 'lt'
              gf_field += '_lt'
            when 'eq'
              gf_field += '_eq'
            when 'ne'
              gf_field += '_neq'
          end
          fs_tmp[gf_field.to_sym] = gf_value
      end
      if not fs_tmp.empty?
        fs.merge!(fs_tmp)
      end
    end
    fs
  end
end

4.其他Controller通过直接使用wando_grid方法即可自动构造Wando.grid.Panel

posted @ 2013-04-08 15:06  Justin_lu  阅读(399)  评论(0编辑  收藏  举报