對Extjs的使用,在做系統的時候用的最多的是formPanel和Panel,這個和其他的TextField、ComboBox、DateField、Checkbox、RadioGroup等一樣都是form里邊的控件,而后五中還有其他類似的控件可以放到formPanel里邊,我用到的功能大多數情況下布局,即'form'和'column'布局,當然除了本文介紹的panel內放各種小控件,也可以在外層定義一個大panel內部讓各種小的panel或者GridPanel。
定義與布局
Ipms.projects.ProjectEditPanel_BasicPanel = function (title, project, isShow) {
this._textFieldName=new Ext.form.TextField({
fieldLabel: '所屬學院',
value: project.get('collegeName'),
disabled: true,
readOnly: isShow,
allowBlank: false,
width: 200
});
Ipms.projects.ProjectEditPanel_BasicPanel.superclass.constructor.call(this, { title: this._title, frame: true,//設置成true之后,頁面外邊是圓角框,但是圓的不是太厲害。 style: 'padding:2px; width:1200px',
border : false,// 表示沒有邊框,如果為true的話,會顯示一條比較細的藍色線條,用在GridPanel上其中的列在顯示index的時候會比較好看 closable: false,//不可以關閉,即當前的panel顯示的時候右上角是否會出現號,點擊后可關閉當前頁面 labelWidth: 80,//設置panel內部的控件的labelWidth為80, bodyStyle: 'padding:5px 5px 0',//設置整體樣式 style: 'margin-bottom: 2px',//設置樣式 defaultType: 'textfield',//設置默認的元素為textField類型
fileUpload:false,//如果panel上有fileUpload控件的話,需要設置成true,才能在后台讀出,否則后台讀不到。 titleCollapse: true,//設置是否可折疊,設置為true時,會在標題所在行的最后部分出現小三角,,點擊折疊后只剩標題,
但是再點擊折疊后的按鈕會顯示原來的panel layout: 'form',//默認的布局方式,Extjs的form布局的含義是將容器按照橫向划分,其中的一個item就占一行,下一個item就排在上一個的下面,
如果其中再裝一個panel,那么這個panel內部還可以同父panel一樣的方式布局 autoHeight: true,//自動高度,在formPanel里用的不多,在GridPanel內部用的較多,有幾條數據就顯示幾條不會出現很多空白的地方。 height: 700,//如果定義了autoHeight再定義height,就會覆蓋原來的自動高度,不能隨着內容的多少改變當前的高度 buttonAlign: 'center',//設置內部button的排版方式為居中 items: [new Ext.Panel({ layout: 'column',//Extjs的column布局方式,其中的元素是按照縱向布局的,即一個元素占一列,后邊的元素排在當前元素的右面 width: 800,//設置寬度,也可以用columnWidth : .25,這種方式表示百分比,即設置3列,3列的列寬分別為50%、25%、 items: [new Ext.Panel({ width: 400, layout: 'form', items: [this._textField1] }), new Ext.Panel({ width: 400, layout: 'form', items: [this._textField2] })]//這兩個panel在layout為column的父panel內就是按照列進行布局的,每個寬度為400,其中兩個panel內部的元素也可以設置多個,其布局方式為form。 }), this._checkboxIsProjectSecondCollege,//這個元素就放在上面兩個元素的下面,因為其所在的panel的布局方式為form,是橫向布局的 new Ext.Panel({ layout: 'column', width: 800, items: [new Ext.Panel({ width: 400, layout: 'form', items: [this._textField3] }), new Ext.Panel({ width: 400, layout: 'form', items: [this._comboBox1]//添加的comboBox控件 })] }), this._textArea1, this._textArea2]//添加的下面兩個textArea控件 })
除了這種先按照行布局然后再進行列布局的方式,也可以先列再行,就看需要什么樣的界面了。Extjs在布局上還是挺靈活的
//在這里,各items內部的this._*的元素是定義的各種小的TextField控件,如代碼前部分所表示的,小的控件各自定義完之后,按照相應的布局方式存放到formPanel內部,
更簡單明了. } Ext.extend(Ipms.projects.ProjectEditPanel_BasicPanel, Ext.form.FormPanel, {});//這種定義的方式是仿照Extjs的api文檔,采用類似類的繼承模式,
便於規范代碼.
FormPanel的submit()表單提交功能
button.panel._expertApplyExitPanel_ProjectPanel.getForm().submit({ url: Ipms.service.expertApplys.ExpertApplyService + '/UploadProjectDocument',//提交數據的路徑 waitMsg: '正在上傳項目文檔',//顯示的loadMask scope: this, method: 'post',//提交方法為post //數據提交成功時的回調函數 success: function (form, action) { var jsonData = Ext.util.JSON.decode(action.response.responseText); var filePath = jsonData.guid; expertApply.set('projectDeclarePath', filePath); saveExpertApply(expertApply, button, myMask,isCommit); } //這里其實省略了一個failure函數,因為我在 后台返回的json數據只有一個success, Response.Write("<html><body>{ success: true, id: '" + ps.getID(Database) + "' }</body></html>"); 沒有定義failure,所以省去了。服務器端接受參數並返回json格式的處理結果,前台接受並處理返回的JSON數據,后台字符串通過Ext.util.JSON.decode
轉成json字符串不能自動根據json字符串success的值來選擇流程 ,需要根據obj.success的值來判斷作出下一步的操作。 })
在具體操作的過程中,我並沒有用submit的方式提交很多數據,這個方法只用了一次,用來提交含有FileUploadField控件中的文檔然后返回其guid的過程中使用的。我所用到的Extjs前后台交互大部分都用的Ajax異步調用的形式和GridPanel的xmlReader的形式獲取數據。不過做到這個地方的時候突然發現formPanel的submit功能也是挺好用的。
之所以在開發系統的過程中實驗室的各種大牛們沒有選擇過多的使用formPanel的submit功能,個人認為是,開發過程中我們用到了很多表格,對應的建立了很多record,而且根據后台cs文件的類,在前端建立的record和后台的實體類一一對應起來,數據傳遞的時候只要用一個Ajax就可以實現不管是一個panel還是一個大panel上嵌套了多個小panel,都可以封裝到同一個'類'中實現對應類的整體保存或讀取,簡單方便直觀,最重要的是通用,何樂而不為呢。
查閱資料顯示,FormPanel中的 form對象為Ext.form.BasicForm類型的對象,它有load和submit方法分別用於加載數據和提交數據。而這兩個方法都是通過調用 Ext.form.BasicForm中的doAction方法來操作的。
doAction方法帶有兩個參數,其中第二個參數為從load或submit 方法傳遞過來的Ext.form.Action對象的配置數據(Config Options)。其中的success和failure屬性是用於處理請求成功或失敗的函數。雖然剛開始的時候並不知道所有的東西都是基於basicPanel來完成的,但是對內部控件賦值的時候的setValue或者value:'',還是比較好用的。
Extjs的TabPanel面板的樣式如下
定義的時候就是
Ext.extend(Ipms.projects.ProjectShowTabPanel, Ext.TabPanel, {});//表示繼承自Ext.TabPanel
其中的內容如下
id: this._id, iconCls: this._iconCls,//css樣式 title: this._title,//整個大panel的標題 style: 'padding:2px; width:1200px', closable: true,//可關閉,同一般的panel,允許右上角出現小叉號 layoutOnTabChange: true,//當選擇不同的標簽時開始渲染布局元素 deferredRender: false,//是否在顯示每個標簽的時候再渲染標簽中的內容.默認true enableTabScroll: true,//當Tab標簽過多時,出現滾動條 activeTab: 0,//初始顯示第幾個Tab頁,可以根據條件加判斷從而激活不同的頁面 frame: true, defaults: { autoHeight: true }, items: items//放置的不同的標簽
同時可以根據不同的條件將某幾個標簽去掉
listeners: { render: function () {//為每個Tab標簽添加監聽器.當標簽渲染時觸發 ,定義在當前激活的標簽的初始化渲染事件中。 if (isShow) { if (!project.get('isCommunateConstruct')) { this.ownerCt.remove(6);//獲得根TabPanel后去掉號為6的標簽,這里的標簽是從0開始排序的 } if (!project.get('isTeemConstruct')) { this.ownerCt.remove(5); } if (!project.get('isContentConstruct')) { this.ownerCt.remove(4); } if (!project.get('isConditionConstruct')) { this.ownerCt.remove(3); this.ownerCt.remove(2); this.ownerCt.remove(1); } if (project.get('isConditionConstruct') && isCollege) this.ownerCt.remove(3); } }
實際在工作的時候,發現TabPanel的remove挺好用的,而且如果去掉其中的一個標簽,就相當於初始化一次,既當remove掉一個標簽,總數隨及減少,於是我就倒着減少,這樣不會影響前面的判斷。
上面這段代碼還顯示了一個問題:當頁面加載時,為其添加監聽事件,listeners:內部的代碼語法是js內部定義的,這里的render是在頁面渲染時觸發的事件,對於grid也可以在內部協商this.store.load(),表示當頁面加載時顯示整個store內部的東西。而對於像store之類的對象,還可以有load、beforeload、onload等事件,具體有多少事件,可以去查API,也可以自己定義,或者直接修改Ext的Debug文件(不建議)。