Javascript 使用 ExtJS 创建动态网格

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10993045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:55:52  来源:igfitidea点击:

Creating a Dynamic Grid with ExtJS

javascriptextjsextjs4gridpanelextjs4.1

提问by ilhan

I'm trying to make a Dynamic Grid class (where I do not know any information about the columns but they are given from the json response and the gird prepares itself accordingly). HereI have found exactly what I was looking for however it gives me an error:

我正在尝试创建一个动态网格类(我不知道关于列的任何信息,但它们是从 json 响应中给出的,网格会相应地准备自己)。在这里,我找到了我正在寻找的内容,但它给了我一个错误:

me.model is undefined
me.setProxy(me.proxy || me.model.getProxy());
ext-all-debug.js (line 47323)

I have tried to add both proxy and model but I was not successful, I kept getting the same error.

我试图同时添加代理和模型,但没有成功,我一直收到同样的错误。

Here is the ExtJS code that I'm working on:

这是我正在处理的 ExtJS 代码:

 // ExtJS 4.1
 Ext.Loader.setConfig({
     enabled: true
 });
 Ext.Loader.setPath('Ext.ux', '../extjs-4.1.0/examples/ux');
 Ext.require([
     'Ext.grid.*',
     'Ext.data.*', ]);


 Ext.define('DynamicGrid', {
     extend: 'Ext.grid.GridPanel',
     storeUrl: '',
     enableColumnHide: true,
     initComponent: function () {
         var store = new Ext.data.Store({
             url: this.storeUrl,
             reader: new Ext.data.JsonReader(),
             autoLoad: true,
             scope: this,
             listeners: {
                 scope: this,
                 metachange: function (store, meta) {
                     if (typeof (store.reader.jsonData.columns) === 'object') {
                         var columns = [];
                         /**
                          * Adding RowNumberer or setting selection model as CheckboxSelectionModel
                          * We need to add them before other columns to display first
                          */
                         if (this.rowNumberer) {
                             columns.push(new Ext.grid.RowNumberer());
                         }
                         if (this.checkboxSelModel) {
                             columns.push(new Ext.grid.CheckboxSelectionModel());
                         }
                         Ext.each(store.reader.jsonData.columns, function (column) {
                             columns.push(column);
                         }); // Set column model configuration 
                         this.getColumnModel().setConfig(columns);
                         this.reconfigure(store, this.getColumnModel());
                     }
                 }
             }
         });
         var config = {
             title: 'Dynamic Columns',
             viewConfig: {
                 emptyText: 'No rows to display'
             },
             loadMask: true,
             border: false,
             stripeRows: true,
             store: store,
             columns: []
         }
         Ext.apply(this, config);
         Ext.apply(this.initialConfig, config);
         DynamicGrid.superclass.initComponent.apply(this, arguments);
     },
     onRender: function (ct, position) {
         this.colModel.defaultSortable = true;
         DynamicGrid.superclass.onRender.call(this, ct, position);
     }
 });

 Ext.onReady(function () {

     Ext.QuickTips.init();

     var grid = Ext.create('DynamicGrid', {
         storeUrl: 'http://300.79.103.188/ApplicationJs/jsontest.json'
     });

     var depV = Ext.create('Ext.Viewport', {
         title: 'Departman Tan?mlar?',
         layout: 'fit',
         items: grid
     }).show();

 });

What I have to do inorder to make it run?

我必须做什么才能让它运行?

采纳答案by vanderwyst

That is a pretty old post so you may have more workarounds coming soon, but that error is because you do not have a model configor fields configdefined for your store. The model will also need to be defined dynamically if you want your grid created with json data alone.

这是一篇很旧的帖子,因此您可能很快就会有更多解决方法,但该错误是因为您没有为您的商店定义模型配置字段配置。如果您希望单独使用 json 数据创建网格,则还需要动态定义模型。

As far as I know, the fields config is pretty forgiving, so you may be able to just set this with a maximum possible number of fields like 20 or 30 or so, but the field names would have to match with the json field names for it to be usable. I.e. if you use:

据我所知,字段配置非常宽容,因此您可以将其设置为最大可能数量的字段,例如 20 或 30 左右,但字段名称必须与 json 字段名称匹配它是可用的。即,如果您使用:

var store = new Ext.data.Store({
    url: this.storeUrl,
    reader: new Ext.data.JsonReader(),
    fields: [
        'column1',
        'column2',
        'column3',
        'column4',
        'column5',
        // etc
    ],

Then your json data would need to come from the database like:

然后你的 json 数据需要来自数据库,如:

[{"column1":"data1", "column2":"data2", // etc

Another thing I've done in the past is to have a reference store loaded first which contained a record with the name and datatype for each of the dynamic fields (meta data). Then I iterated through this reference store and added a model fieldandthe column definition at each iteration, thenI loaded the grid's store which now had the correct data model defined and the grid would have the correct column defintion.

我过去做过的另一件事是首先加载一个引用存储,其中包含一个记录,其中包含每个动态字段(元数据)的名称和数据类型。然后我遍历这个引用存储并在每次迭代时添加一个模型字段列定义,然后我加载网格的存储,它现在定义了正确的数据模型,并且网格将具有正确的列定义。

You may have do something like that if you don't want to make your database return generic column names as covered above, because I don't know how you will load the data into your grid store initially beforeyou give it a data model to use.

如果你不想让你的数据库返回上面提到的通用列名,你可能已经做了类似的事情,因为我不知道你给它一个数据模型之前你将如何将数据加载到网格存储中用。

UPDATE 13 Jun:

6 月 13 日更新:

I haven't tried it yet, but I just came across this in the 4.1 docs(scroll down to the "Response MetaData" section in the intro). It describes using metaData in your json response to accomplish exactly what you are going for with a dynamic model and grid columns.

我还没有尝试过,但我刚刚在 4.1 文档中遇到了这个(向下滚动到介绍中的“响应元数据”部分)。它描述了在你的 json 响应中使用 metaData 来完成你想要的动态模型和网格列。

You would probably still have to do the iteration I described above once you process the metaData, but you can use it to cut out that additional request to get the meta data.

一旦您处理了元数据,您可能仍然需要执行我上面描述的迭代,但是您可以使用它来减少获取元数据的额外请求。

I suppose if your field configuration doesn't change with each request then it would be easier to simply to do the extra request at the beginning, but if you want something really dynamic this would do it.

我想如果你的字段配置不会随着每个请求而改变,那么在开始时简单地做额外的请求会更容易,但如果你想要一些真正动态的东西,那就可以了。

回答by Justin Noel

NOTE: This is a duplicte to my response here : How do you create table columns and fields from json? (Dynamic Grid). I just wanted address my final solution in all of the StackOverflow questions I used to solve this problem.

注意:这是我在此处回复的重复内容:如何从 json 创建表列和字段?(动态网格)。我只是想在我用来解决这个问题的所有 StackOverflow 问题中解决我的最终解决方案。

Stackoverflow is littered with questions very similar to this one. I worked through them all and did not find a definitive solution. However, most of the provided answers pointed me in the right direction. I'll give me best shot at putting all those suggestions together and making this clear for others:

Stackoverflow 充斥着与这个非常相似的问题。我研究了所有这些,但没有找到明确的解决方案。但是,大多数提供的答案都为我指明了正确的方向。我会给我最好的机会,把所有这些建议放在一起,并让其他人清楚这一点:

Model:(Only shows 2 fields that will be in all JSON responses. Will still be overwritten)

模型:(仅显示将在所有 JSON 响应中的 2 个字段。仍将被覆盖)

Ext.define('RTS.model.TestsModel', {
    extend: 'Ext.data.Model',
    alias: 'model.TestsModel',

    fields: [
        {
            name: 'poll_date'
        },
        {
            name: 'poller'
        }
    ]
});

Store:

店铺:

Ext.define('RTS.store.TestsStore', {
    extend: 'Ext.data.Store',
    alias: 'store.TestsStore',

    model: 'RTS.model.TestsModel',

    constructor: function(cfg) {
        var me = this;

        cfg = cfg || {};

        me.callParent([Ext.apply({
            autoLoad: false,
            proxy       : {
                type    : 'ajax',
                url     : 'tests.php',
                reader  : {
                    type    : 'json',
                    root    : 'tests',
                    successProperty : 'success'
                }
            },            
            storeId: 'tests-store'
        }, cfg)]);
    }
});

View:(The columns will be defined in each JSON response)

查看:(列将在每个 JSON 响应中定义)

Ext.define('RTS.view.TestsView', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.TestsView',

    id: 'tests-view',
    title: 'Tests',
    emptyText: '',
    store: 'TestsStore',

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            viewConfig: {

            },
            columns: [
            ]
        });

        me.callParent(arguments);
    }

});

Controller:(The controller does all the work in forcing the view and model to change based on the JSON response).

控制器:(控制器根据 JSON 响应完成强制视图和模型更改的所有工作)。

Ext.define('RTS.controller.TestsController', {
    extend: 'Ext.app.Controller',
    alias: 'controller.TestsController',

    stores: [
        'TestsStore'
    ],
    models: [
        'TestsModel'
    ],
    views: [
        'TestsView'
    ],

    init: function(application) {

        // When store changes, trigger an event on grid
        // to be handled in 'this.control'.  

        // NOTE : Ext JS does not allow control of 
        // non-component events.

        // Ext JS 4.2 beta will allow the controller
        // to detect non-component changes and handle them
        var testsStore = this.getStore('TestsStore');
        testsStore.on("metachange", metaChanged, this);
        function metaChanged(store, meta) {
            var grid = Ext.ComponentQuery.query('TestsView')[0];
            grid.fireEvent('metaChanged', store, meta);
        };


        this.control({
            "TestsView": {
                metaChanged: this.handleStoreMetaChange
            }
        });
    },

    /**
     * Will update the model with the metaData and
     * will reconfigure the grid to use the
     * new model and columns.
     */
    handleStoreMetaChange: function(store, meta) {
        var testsGrids = Ext.ComponentQuery.query('TestsView')[0];
        testsGrids.reconfigure(store, meta.columns);
    }

});

JSON Response:Your json response must have the "metaData" property included. It should define the fields just as you would on a static model and the view that would normally be defined to show the fields.

JSON 响应:您的 json 响应必须包含“metaData”属性。它应该像在静态模型和通常定义为显示字段的视图上一样定义字段。

{
    "success": true,
    "msg": "",
    "metaData": {
        "fields": [
            {
                "name": "poller"
            },
            {
                "name": "poll_date"
            },
            {
                "name": "PING",
                "type": "int"
            },
            {
                "name": "SNMP",
                "type": "int"
            },
            {
                "name": "TELNET",
                "type": "int"
            },
            {
                "name": "SSH",
                "type": "int"
            },
            {
                "name": "all_passed"
            }
        ],
        "columns": [
            {
                "dataIndex": "poller",
                "flex": 1,
                "sortable": false,
                "hideable": false,
                "text": "Poller"
            },
            {
                "dataIndex": "poll_date",
                "flex": 1,
                "sortable": false,
                "hideable": false,
                "text": "Poll Date"
            },
            {
                "dataIndex": "PING",
                "flex": 1,
                "sortable": false,
                "hideable": false,
                "text": "PING",
                "renderer": "RenderFailedTests"
            },
            {
                "dataIndex": "SNMP",
                "flex": 1,
                "sortable": false,
                "hideable": false,
                "text": "SNMP",
                "renderer": "RenderFailedTests"
            },
            {
                "dataIndex": "TELNET",
                "flex": 1,
                "sortable": false,
                "hideable": false,
                "text": "TELNET",
                "renderer": "RenderFailedTests"
            },
            {
                "dataIndex": "SSH",
                "flex": 1,
                "sortable": false,
                "hideable": false,
                "text": "SSH",
                "renderer": "RenderFailedTests"
            },
            {
                "dataIndex": "all_passed",
                "flex": 1,
                "sortable": false,
                "hideable": false,
                "text": "All Passed",
                "renderer": "RenderFailedTests"
            }
        ]
    },
    "tests": [
        {
            "poller": "CHI",
            "poll_date": "2013-03-06",
            "PING": "1",
            "SNMP": "0",
            "TELNET": "1",
            "SSH": "0",
            "all_passed": "0"
        },
        {
            "poller": "DAL",
            "poll_date": "2013-03-06",
            "PING": "1",
            "SNMP": "0",
            "TELNET": "1",
            "SSH": "0",
            "all_passed": "0"
        },
        {
            "poller": "CHI",
            "poll_date": "2013-03-04",
            "PING": "1",
            "SNMP": "0",
            "TELNET": "1",
            "SSH": "0",
            "all_passed": "0"
        },
        {
            "poller": "DAL",
            "poll_date": "2013-03-04",
            "PING": "1",
            "SNMP": "0",
            "TELNET": "1",
            "SSH": "0",
            "all_passed": "0"
        },
        {
            "poller": "CHI",
            "poll_date": "2013-03-01",
            "PING": "1",
            "SNMP": "0",
            "TELNET": "1",
            "SSH": "0",
            "all_passed": "0"
        }
    ]
}