Skip to main content

[探索 10 分鐘] Extjs.ComboBox 用 ajax 方式讀取選項資料 (php + Yii + extjs + mysql)


在 CNIS (Canadian Network for International Surgery, 非營利組織) 當志工時推薦他們一個我比較熟悉的 Extjs framework, 但這個框架其實不好上手。同事問我怎麼從 db 撈一組國家列表, 前端用 Extjs 的 combobox 元件來互動 ? 於是我就動手了, 發現還真的挺複雜的, 所以趕快來記錄一下。

需求重點提示

  1. 這個下拉式選單 (combobox) 的內容是透過 ajax 初始化他的可用選項
  2. 獨立創建一個 controller.js 專門接收這個 request, 並與 MySQL 完成交互, 回傳 JSON 格式資料
  3. 需存取 stored-procedure
  4. combobox 需有一個 template 方便調整符合站台的樣式 (他們不要 Extjs 內建的樣式)

程式筆記

MySQL Store Procedure

CREATE DEFINER=`my_db`@`%` PROCEDURE `my_sp`(  
)  
 BEGIN  
      SELECT  
       `country_code` AS `key`,  
       `country_name` AS `name`  
      FROM `myDB`.`myTable`; 
 END$$

controller.php

Yii framework 有個驗證機制, 需要 allow 給什麼 user 可存取什麼 controller, 要記得加上這一段代碼 (如下 accessRules 函式), 否則會得到 server side 的訊息: 
failed to load resource the server responded with a status of 403 (access forbidden)
controller
// authorize the access permission  
public function accessRules() {
 return array(  
  ...,  
  array('allow',   
    'actions'=>array('create','update','createExtJS','retrieveCode'),  
    'users'=>array('@'),  
  ),...  
 );  
 }  

 public function actionRetrieveCode($type) {  
   Yii::log("====== Create Ajax calling ========", CLogger::LEVEL_INFO);  
   $command = Yii::app()->db->createCommand('CALL my_SP ()');  
   $rawData = $command->queryAll();  
   $json = array(  
  'success' => count($rawData) > 0,  
  'totalCount' => count($rawData),  
  'data' => $rawData  
   );       
   echo json_encode($json);                 
} 

front-end.js

這邊就是 Extjs 主要的實作
 Ext.define('Combo.model.Pair', {  // common model for each combobox featured in key-value pair
                     extend: 'Ext.data.Model',  
                     fields: ['key', 'name']  
                }); 
myStore = Ext.create('Ext.data.Store', {  
                     id:'codeCountry',  
                     model: 'Combo.model.Pair',    
                     autoLoad:true,  
                     proxy: {  
                          type: 'ajax',  
                          url : '/myApp/index.php?r=myPage/myController&type=Country',  
                          reader: {  
                               type: 'json',  
                               root: 'data',  
                               successProperty: 'success'  
                          }  
                     },  
                     listeners: {  
                          load: function () {  
                                // set the default value after the store loads  
                                Ext.getCmp('CbRelatedCountries').setValue(Ext.getCmp('CbRelatedCountries').getStore().getAt(0).get(Ext.getCmp('CbRelatedCountries').valueField));  
                          }  
                     }       
                });  
 this.codeRegion = Ext.create('Ext.data.Store', {  
                     id:'codeRegion',  
                     model: 'Combo.model.Pair',    
                     autoLoad:true,  
                     proxy: {  
 ... }}); 

tpl_for_combobox.js

還記得需求有提到需要有自定義的 combobox 樣式嗎 ? 所以需增加這個 template
{xtype: 'combobox', id: 'CbRelatedCountries', name: 'CbRelatedCountries', fieldLabel: 'Related Countries', allowBlank: false, labelWidth: 150, width: 500,  
                      forceSelection: true,  
                      multiSelect: true,  
                      triggerAction: 'all',  
                      lazyRender: true,  
                      listConfig:{  
                              itemTpl:new Ext.XTemplate('<tpl for="."><div class="x-combo-list-item">{key} : {name}</div></tpl>')  
                      },  
                      emptyText: '-- Select Options --',  
                      queryMode: 'local',  
                      displayField: 'key',  
                      valueField: 'key',  
                      submitValue: false,  
                      store: myStore  
}
有興趣的同學也可以留言交流。

參考資料

  • http://docs.sencha.com/extjs/3.4.0/

Comments