Extjs create a grid feature or grid plugin that sets a tooltip for each column in the grid

后端 未结 2 749
星月不相逢
星月不相逢 2021-01-20 02:39

This question has the answer to adding the tooltip: Extjs4 set tooltip on each column hover in gridPanel

I have a follow up question to the most upvoted answer to t

2条回答
  •  梦毁少年i
    2021-01-20 02:56

    I took the accepted answer to the next logical conclusion:

    And made this into complete configurable plugin based solution, that requires very little configuration to use. And plays nicely with Sencha Architect.

    Motivation

    The main motivation for researching this and getting it to work is that the DateColumn has the renderer config parameter marked as hidden so that Sencha Architect doesn't allow you to modify it in the Config panel. I understand why and it drove me to this solution, which I think is the correct one and the most maintainable and reusable in the long run.

    At the time of this writing:

    I am using Sencha Architect 3.x and ExtJS 4.2.2, these instructions are included on how to apply these features in that environment. If you don't use Sencha Architect, you will just have to create and manage the files yourself. I find it extremely productive when working on any size ExtJS project.

    First is the actual GridPlugin:

    Add a JSResource to your project, set the url to js/CellToolTip.js, and then copy the following code as its contents.

    js/CellToolTip.js

    Ext.define('Ext.grid.plugin.CellToolTip', {
        extend: 'Ext.AbstractPlugin',
        alias: 'plugin.CellQTip',
        config: {
            debug: false
        },
    
        init: function(grid) {
    
            // You may not need the scope, but if you do, this binding will
            // allow to preserve the scope configured in the column...
            var pluginRenderer = Ext.Function.bind(this.renderer, this);
    
            Ext.each(grid.query('gridcolumn'), function(col) {
                var renderer = col.renderer;
                col.renderer = renderer ? Ext.Function.createSequence(renderer, pluginRenderer) : pluginRenderer;
            });
        },
    
        renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
            var col = view.getGridColumns()[colIndex];
            var fn = this[col.itemId];
            if (fn) {
                metaData.tdAttr = fn(value, metaData, record, rowIndex, colIndex, store, view);
            }     
            return value;
        }
    });
    

    Here is how you apply it to a GridPanel:

    You add what is called a Process Config function to each GridPanel that you want to apply the plugin to:

    What this does is it acts as an interceptor function and allows you to modify the config of the Component before it is actually applied.

    processBlobInfoGridPanel: function(config) {
        var ttp = Ext.create('Ext.grid.plugin.CellToolTip', {
            createdOn: function(value, metaData, record, rowIndex, colIndex, store, view) { return 'data-qtip="' + value.toUTCString() + '"'; },
            byteSize: function(value, metaData, record, rowIndex, colIndex, store, view) { return 'data-qtip="' + value + ' bytes"'; }
        });
        config.plugins = [ttp];
        return config;
    },
    

    How to add these to a Sencha Architect project:

    First what this does is creates the plugin with its own config where each attribute is the itemId of each Column that you want to apply the plugin to.

    The function that is associated with each Column has the exact same signature as the renderer config.

    Here the function implementations are short and in a single line. This is just an and example is for brevity.

    ToolTip functions explained:

    createdOn adds a ToolTip for each Cell in that Column as the time in UTC.

    byteSize adds a ToolTip for each Cell in that Column that shows the raw number of bytes as a detail.

    Then it adds the instance of the configured plugin to the config of the GridPanel and returns the instance of the config.

    Bonus Class

    In Sencha Architect I created a Column to represent the Size of Resources, I wanted to show the byte size as a human readable format with the largest appropriate interval. So I added a renderer function to do this.

    I realized I was going to need this Column on multiple GridPanel instances so promoted it to a Class.

    The way you do this is you right click on the Column and pick Promote to Class. Sencha Architect then creates the following code and puts it in a file in your app/view directory with the name of the file equal to the userClassName you specified in the Config panel.

    Ext.define('AdminApp.view.ByteSize', {
        extend: 'Ext.grid.column.Column',
        alias: 'widget.byteSize',
    
        itemId: 'byteSize',
        dataIndex: 'size',
        text: 'Size',
        tooltip: 'Byte size in human readable format',
    
        initComponent: function() {
            var me = this;
    
            me.callParent(arguments);
        },
    
        renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
            // convert bytes into a human readable format"
            var bytes = value;
            if      (bytes>=1073741824) {bytes=(bytes/1073741824).toFixed(2)+' GB';}
            else if (bytes>=1048576)    {bytes=(bytes/1048576).toFixed(2)+' MB';}
            else if (bytes>=1024)       {bytes=(bytes/1024).toFixed(2)+' KB';}
            else if (bytes>1)           {bytes=bytes+' bytes';}
            else if (bytes==1)          {bytes=bytes+' byte';}
            else                        {bytes='0 byte';}
            return bytes;
        }
    
    });
    

    Now the original instance of this Column is pointing to this new Class:

    columns: [
        {
            xtype: 'byteSize',
            itemId: 'byteSize'
        }
    ]
    

    Now to use this in other GridPanel instances in Sencha Architect, just right click on the Column instance that is linked to this new class and select Duplicate. Then drag the duplicated instance to the GridPanel you want to use the ByteSize class and drop it in the list of Columns. Then configure each cloned instance independently of the others.

    Any changes to the default or behavior of the ByteClass automatically affect all the instances.

    Roadmap

    This is a first working minimally viable solution, there are obvious enhancements that can be made. For example, I am want to fix it where it appends to metaData.tdAttr if there is already content instead of blindly over-writing what is there.

    Any enhancements will be done to this Gist on GitHub.

提交回复
热议问题