Ext面向对象开发实践

本文介绍了一个使用ExtJS框架实现的GridPanel示例程序,展示了如何通过GridPanel展示数据、添加工具条按钮及提供弹出式窗体以实现数据的新增功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是自己在学习Ext过程中一个写的一个示例程序,仅为练习,功能并不全,现将其记录在我的博客中,希望可以和学习Ext的朋友一起分享。

效果图

 

示例程序简述:

这个Demo为了演示如将使用GridPanel显示数据,并为GridPanel添加工具条按钮,提供弹出式窗体新增数据。

 

使用到的Ext组件

这个Demo涉及到Ext中的GridPanel,FormPanel和Window三个组件。

 

 

 

现在开始讲解代码,首先看一下创建GridPanel的代码片段

  1. //定义数据列表面板类
  2. PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
  3.     //用于新增数据的窗体
  4.     insertWin: null,
  5.     
  6.     constructor: function() {
  7.         //添加自定义事件
  8.         this.addEvents("rowSelect");
  9.         
  10.         this.insertWin = new InsertPersonInfoWindow(); //创建数据添加窗体
  11.         this.insertWin.on("submit"this.onInsertWinSubmit, this); //为数据创建窗体指定Submit事件处理句柄
  12.         
  13.         PersonListGridPanel.superclass.constructor.call(this, {
  14.             renderTo: Ext.getBody(),
  15.             width: 360,
  16.             height: 300,
  17.             frame:true,
  18.             sm: new Ext.grid.RowSelectionModel({
  19.                 singleSelect:true,
  20.                 listeners: {
  21.                     "rowselect": {
  22.                         fn: function(sm, rowIndex, r) {
  23.                             this.fireEvent("rowSelect", r); //触发自定义事件
  24.                         },
  25.                         scope: this
  26.                     }
  27.                 }
  28.             }),
  29.             store: new Ext.data.JsonStore({
  30.                     data: [{name: "李宗盛", age: 28, sex: "男"}, {name: "林忆莲", age: 26, sex: "女"}],
  31.                     fields: ["name""sex""age"]
  32.             }),
  33.             draggable: false,
  34.             enableColumnMove: false,
  35.             title: "First Grid",
  36.             //iconCls:'icon-grid',
  37.             colModel: new Ext.grid.ColumnModel([
  38.                 {header: "Staff Name", width: 100, menuDisabled: true},
  39.                 {header: "Age", width: 100, sortable: true, dataIndex: "age", align: "right", tooltip: "这里是提示信息"},
  40.                 {header: "Sex", width: 100, sortable: true, dataIndex: "sex", align: "center"}
  41.             ]),
  42.             tbar: [{
  43.                 text: "添加人员",
  44.                 handler: function() {
  45.                     this.insertWin.show();
  46.                 },
  47.                 scope: this
  48.             }]
  49.         });
  50.     },
  51.     getActiveRecord: function() {
  52.         var sm = this.getSelectionModel();
  53.         return (sm.getCount() === 0) ? null : sm.getSelected();
  54.     },
  55.     insert: function(r) {
  56.         this.getStore().add(r);
  57.     },
  58.     onInsertWinSubmit: function(win, r) {
  59.         this.insert(r);
  60.     }
  61. });

数据维护面板代码

  1. //定义数据维护面板,在后面定义的新增和修改窗体中都会使用到该面板
  2. PersonInfoFormPanel = Ext.extend(Ext.form.FormPanel, {
  3.     constructor: function() {
  4.         PersonInfoFormPanel.superclass.constructor.call(this, {
  5.             //title: "Person Info",
  6.             frame: true,
  7.             width: 360,
  8.             labelWidth: 40,
  9.             defaultType: "textfield",
  10.             defaults: { anchor: "92%" },
  11.             items: [{
  12.                 name: "name"//注意,这里使用name属性而不是id,因为PersonInfoFormPanel会被添加和插入两个窗体使用,使用id会有冲突,导致组件不能被正确显示
  13.                 fieldLabel: "Name",
  14.                 allowBlank: false,
  15.                 emptyText: "请输入姓名",
  16.                 blankText: "姓名不能为空"
  17.             }, {
  18.                 name: "age",
  19.                 fieldLabel: "Age",
  20.                 vtype: "age"
  21.             }, {
  22.                 hiddenName: "sex",
  23.                 xtype: "combo",
  24.                 fieldLabel: "Sex",
  25.                 
  26.                 store: new Ext.data.SimpleStore({
  27.                     fields: [
  28.                        {name: 'Sex'}
  29.                     ],
  30.                     data:[["男"], ["女"]]
  31.                 }),
  32.                 mode: 'local',
  33.                 displayField:'Sex',
  34.                 triggerAction: 'all',
  35.                 emptyText:'选择性别...'
  36.             }]
  37.         })
  38.     },
  39.     getValues: function() {
  40.         if (this.getForm().isValid()) {
  41.             return new Ext.data.Record(this.getForm().getValues());
  42.         }
  43.         else {
  44.             throw Error("Error Message");
  45.         }
  46.     },
  47.     setValues: function(r) {
  48.         this.getForm().loadRecord(r);
  49.     },
  50.     reset: function() {
  51.         this.getForm().reset();
  52.     }
  53. });

数据新增窗体代码

  1. //定义新增数据窗体
  2. InsertPersonInfoWindow = Ext.extend(Ext.Window, {
  3.     form: new PersonInfoFormPanel(), //这句可以写在这里是因为PersonInfoFormPanel定义在该类之前
  4.     
  5.     constructor: function() {
  6.         this.addEvents("submit");
  7.         InsertPersonInfoWindow.superclass.constructor.call(this, {
  8.             title: "添加",
  9.             plain: true,
  10.             width: 360,
  11.             modal: true//模式窗体
  12.             onEsc: Ext.emptyFn,
  13.             closeAction: "hide",
  14.             items: [this.form],
  15.             buttons: [{
  16.                 text: "确  定",
  17.                 handler: this.onSubmitClick,
  18.                 scope: this
  19.             }, {
  20.                 text: "取  消",
  21.                 handler: this.onCancelClick,
  22.                 scope: this
  23.             }]
  24.         });
  25.         //alert(this.onSubmitClick);
  26.     },
  27.     close: function() {
  28.         //需要重写CLose方法,
  29.         //否则在窗体被关闭其实体会被释放
  30.         this.hide();
  31.         this.form.reset();
  32.     },
  33.     onSubmitClick: function() {
  34.         //alert(Ext.util.JSON.encode(this.form.getValues().data));
  35.         try {
  36.             this.fireEvent("submit"thisthis.form.getValues());
  37.             this.close();
  38.         }
  39.         catch(_err) {
  40.             return;
  41.         }
  42.     },
  43.     onCancelClick: function() {
  44.         this.close();
  45.     }
  46. });

HTML中的引用代码

  1.         <script type="text/javascript">
  2.             Ext.QuickTips.init();
  3.             Ext.form.Field.prototype.msgTarget = "side";
  4.             Ext.BLANK_IMAGE_URL = "http://localhost:8080/ext-2.2/resources/images/default/s.gif";
  5.             
  6.             Ext.apply(Ext.form.VTypes, {
  7.                 "age": function(_v) {
  8.                     if (/^/d+$/.test(_v)) {
  9.                         var _age = parseInt(_v);
  10.                         if ((_age > 0) && (_age < 200)) return true;
  11.                     }
  12.                     return false;
  13.                 },
  14.                 "ageText": "年龄必须在0到200之间",
  15.                 "ageMask": /[0-9]/i
  16.             });
  17.             Ext.onReady(function() {
  18.                 new PersonListGridPanel();
  19.             });
  20.         </script>

代码很简洁,也很清晰。只需要创建一个PersonListGridPanel即可,因为它自身包含了新增、修改的窗体对象,而新增和修改窗体中都使用到了负责数据编辑的PersonInfoFormPanel。

在PersonInfoFormPanel中使用了VTypes进行数据验证。

新增和修改窗体仅仅是界面,负责将用户在PersonInfoFormPanel中填写的数据传回到ListGrid中以便保存,或是将ListGrid中的数据传递到PersonInfoFormPanel中进行呈现,供用户编辑。

 

附上完整的HTML代码和JavaScript代码文件。

Grid.html

  1. <html>
  2.     <head>
  3.         <title>Ext Grid</title>
  4.         <link rel="stylesheet" type="text/css" href="http://localhost:8080/ext-2.2/resources/css/ext-all.css"/>
  5.         <script type="text/javascript" src="http://localhost:8080/ext-2.2/adapter/ext/ext-base.js"></script>
  6.         <script type="text/javascript" src="http://localhost:8080/ext-2.2/ext-all.js"></script>
  7.         <script type="text/javascript" src="PersonListGridPanel.js"></script>
  8.         
  9.         <script type="text/javascript">
  10.             Ext.QuickTips.init();
  11.             Ext.form.Field.prototype.msgTarget = "side";
  12.             Ext.BLANK_IMAGE_URL = "http://localhost:8080/ext-2.2/resources/images/default/s.gif";
  13.             
  14.             Ext.apply(Ext.form.VTypes, {
  15.                 "age": function(_v) {
  16.                     if (/^/d+$/.test(_v)) {
  17.                         var _age = parseInt(_v);
  18.                         if ((_age > 0) && (_age < 200)) return true;
  19.                     }
  20.                     return false;
  21.                 },
  22.                 "ageText": "年龄必须在0到200之间",
  23.                 "ageMask": /[0-9]/i
  24.             });
  25.             Ext.onReady(function() {
  26.                 new PersonListGridPanel();
  27.             });
  28.         </script>
  29.     </head>
  30.     <body>
  31.     </body>
  32. </html>

PersonListGridPanel.js

  1. //定义数据列表面板类
  2. PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
  3.     insertWin: null,
  4.     modifyWin: null,
  5.     
  6.     constructor: function() {
  7.         //添加自定义事件
  8.         this.addEvents("rowSelect");
  9.         
  10.         this.insertWin = new InsertPersonInfoWindow();
  11.         this.insertWin.on("submit"this.onInsertWinSubmit, this);
  12.         
  13.         this.modifyWin = new ModifyPersonInfoWindow();
  14.         this.modifyWin.on("submit"this.onModifyWinSubmit, this);
  15.         PersonListGridPanel.superclass.constructor.call(this, {
  16.             renderTo: Ext.getBody(),
  17.             width: 360,
  18.             height: 300,
  19.             frame:true,
  20.             sm: new Ext.grid.RowSelectionModel({
  21.                 singleSelect:true,
  22.                 listeners: {
  23.                     "rowselect": {
  24.                         fn: function(sm, rowIndex, r) {
  25.                             this.fireEvent("rowSelect", r); //触发自定义事件
  26.                         },
  27.                         scope: this
  28.                     }
  29.                 }
  30.             }),
  31.             store: new Ext.data.JsonStore({
  32.                     data: [{name: "李宗盛", age: 28, sex: "男"}, {name: "林忆莲", age: 26, sex: "女"}],
  33.                     fields: ["name""sex""age"]
  34.             }),
  35.             draggable: false,
  36.             enableColumnMove: false,
  37.             title: "First Grid",
  38.             //iconCls:'icon-grid',
  39.             colModel: new Ext.grid.ColumnModel([
  40.                 {header: "Staff Name", width: 100, menuDisabled: true},
  41.                 {header: "Age", width: 100, sortable: true, dataIndex: "age", align: "right", tooltip: "这里是提示信息"},
  42.                 {header: "Sex", width: 100, sortable: true, dataIndex: "sex", align: "center"}
  43.             ]),
  44.             tbar: [{
  45.                 text: "添加人员",
  46.                 handler: function() {
  47.                     //***************************************************
  48.                     //如果没有重写InsertPersonInfoWindow的Close方法
  49.                     //在调用之前需要检查其实例insertWin是否被释放
  50.                     //使用示例:
  51.                     //if (!this.insertWin) {
  52.                     //    this.insertWin = new InsertPersonInfoWindow();
  53.                     //}
  54.                     //this.insertWin.show();
  55.                     //***************************************************
  56.                     this.insertWin.show();
  57.                 },
  58.                 scope: this
  59.             }, "-", {
  60.                 text: "修改人员",
  61.                 handler: function() {
  62.                     var r = this.getActiveRecord();
  63.                     if (!r) return;
  64.                     alert(Ext.util.JSON.encode(r.data));
  65.                     this.modifyWin.load(r);
  66.                     //如何将数据填充到窗体中?
  67.                     this.modifyWin.show();
  68.                 },
  69.                 scope: this
  70.             }, "-", {
  71.                 text: "删除人员"
  72.             }]
  73.         });
  74.     },
  75.     getActiveRecord: function() {
  76.         var sm = this.getSelectionModel();
  77.         return (sm.getCount() === 0) ? null : sm.getSelected();
  78.     },
  79.     insert: function(r) {
  80.         this.getStore().add(r);
  81.     },
  82.     onInsertWinSubmit: function(win, r) {
  83.         this.insert(r);
  84.     },
  85.     onModifyWinSubmit: function(win, r) {
  86.         alert('onModifyWinSubmit');
  87.     }
  88. });
  89. //==============================================================================
  90. //定义数据维护面板,在后面定义的新增和修改窗体中都会使用到该面板
  91. PersonInfoFormPanel = Ext.extend(Ext.form.FormPanel, {
  92.     constructor: function() {
  93.         PersonInfoFormPanel.superclass.constructor.call(this, {
  94.             //title: "Person Info",
  95.             frame: true,
  96.             width: 360,
  97.             labelWidth: 40,
  98.             defaultType: "textfield",
  99.             defaults: { anchor: "92%" },
  100.             items: [{
  101.                 name: "name"//注意,这里使用name属性而不是id,因为PersonInfoFormPanel会被添加和插入两个窗体使用,使用id会有冲突,导致组件不能被正确显示
  102.                 fieldLabel: "Name",
  103.                 allowBlank: false,
  104.                 emptyText: "请输入姓名",
  105.                 blankText: "姓名不能为空"
  106.             }, {
  107.                 name: "age",
  108.                 fieldLabel: "Age",
  109.                 vtype: "age"
  110.             }, {
  111.                 hiddenName: "sex",
  112.                 xtype: "combo",
  113.                 fieldLabel: "Sex",
  114.                 
  115.                 store: new Ext.data.SimpleStore({
  116.                     fields: [
  117.                        {name: 'Sex'}
  118.                     ],
  119.                     data:[["男"], ["女"]]
  120.                 }),
  121.                 mode: 'local',
  122.                 displayField:'Sex',
  123.                 triggerAction: 'all',
  124.                 emptyText:'选择性别...'
  125.             }]
  126.         })
  127.     },
  128.     getValues: function() {
  129.         if (this.getForm().isValid()) {
  130.             return new Ext.data.Record(this.getForm().getValues());
  131.         }
  132.         else {
  133.             throw Error("Error Message");
  134.         }
  135.     },
  136.     setValues: function(r) {
  137.         this.getForm().loadRecord(r);
  138.     },
  139.     reset: function() {
  140.         this.getForm().reset();
  141.     }
  142. });
  143. //==============================================================================
  144. //定义新增数据窗体
  145. InsertPersonInfoWindow = Ext.extend(Ext.Window, {
  146.     form: new PersonInfoFormPanel(), //这句可以写在这里是因为PersonInfoFormPanel定义在该类之前
  147.     
  148.     constructor: function() {
  149.         this.addEvents("submit");
  150.         //Ext.apply(this.form, {baseCls: "x-plain"});
  151.         InsertPersonInfoWindow.superclass.constructor.call(this, {
  152.             title: "添加",
  153.             plain: true,
  154.             width: 360,
  155.             modal: true//模式窗体
  156.             onEsc: Ext.emptyFn,
  157.             closeAction: "hide",
  158.             items: [this.form],
  159.             buttons: [{
  160.                 text: "确  定",
  161.                 handler: this.onSubmitClick,
  162.                 scope: this
  163.             }, {
  164.                 text: "取  消",
  165.                 handler: this.onCancelClick,
  166.                 scope: this
  167.             }]
  168.         });
  169.         //alert(this.onSubmitClick);
  170.     },
  171.     close: function() {
  172.         //需要重写CLose方法,
  173.         //否则在窗体被关闭其实体会被释放
  174.         this.hide();
  175.         this.form.reset();
  176.     },
  177.     onSubmitClick: function() {
  178.         //alert(Ext.util.JSON.encode(this.form.getValues().data));
  179.         try {
  180.             this.fireEvent("submit"thisthis.form.getValues());
  181.             this.close();
  182.         }
  183.         catch(_err) {
  184.             return;
  185.         }
  186.     },
  187.     onCancelClick: function() {
  188.         this.close();
  189.     }
  190. });
  191. //==============================================================================
  192. //定义编辑数据窗体
  193. ModifyPersonInfoWindow = Ext.extend(Ext.Window, {
  194.     form: null,
  195.     
  196.     constructor: function() {
  197.         this.form = new PersonInfoFormPanel();
  198.         //this.form.getComponent("name").readOnly = true;
  199.         
  200.         ModifyPersonInfoWindow.superclass.constructor.call(this, {
  201.             title: "修改",
  202.             plain: true,
  203.             width: 360,
  204.             modal: true//模式窗体
  205.             onEsc: Ext.emptyFn, //禁止使用Esc键关闭窗体
  206.             closeAction: "hide",
  207.             items: [this.form],
  208.             buttons: [{
  209.                 text: "确  定",
  210.                 handler: this.onSubmitClick,
  211.                 scope: this
  212.             }, {
  213.                 text: "取  消",
  214.                 handler: this.onCancelClick,
  215.                 scope: this
  216.             }]
  217.         });
  218.         //alert(this.onSubmitClick);
  219.     },
  220.     close: function() {
  221.         //需要重写CLose方法,
  222.         //否则在窗体被关闭其实体会被释放
  223.         this.hide();
  224.         this.form.reset();
  225.     },
  226.     load: function(r) {
  227.         alert(this.getForm());
  228.         this.form.setValues(r);
  229.     },
  230.     onSubmitClick: function() {
  231.         try {
  232.             this.fireEvent("submit"thisthis.form.getValues());
  233.             this.close();
  234.         }
  235.         catch(_err) {
  236.             return;
  237.         }
  238.     },
  239.     onCancelClick: function() {
  240.         this.close();
  241.     } 
  242. });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值