我们正在尝试构建一个简单的原型来使用ExtJs来使用我们的数据服务(也是为了同时学习ExtJ)。
在开发原型时(具有ExtJS的基础知识),我遇到了几个hickup。在发布问题之前,我想让您快速浏览以下内容。
以下是与服务交互的主类。我们希望确保在ajax通信期间屏蔽/取消屏蔽某些UI组件。
Ext.define('Sample.provider.SvcClient', {
TestConnectivity: function(prms){
debugger;
Ext.Ajax.on('beforerequest', function(conn,o,result) {
prms.BeforeRequest(conn,o,result);
});
Ext.Ajax.on('requestcomplete',function(conn,o,result) {
prms.RequestComplete(conn,o,result);
});
Ext.Ajax.on('requestexception',function(conn,o,result) {
prms.RequestException(conn,o,result);
});
Ext.Ajax.request({
url: prms.Url,
method: prms.HttpMethod,
headers: {
'Authorization' : 'Basic ' + prms.Credentials
},
success: prms.Success,
failure: prms.Failure,
callback: prms.Callback
});
}
});
我们开发了SvcClient的扩展,特别是为了帮助在ajax通信期间屏蔽控件:
Ext.define('Sample.util.ClientProxy', {
CtlToMask : null,
DoTestConnection: function(ctlToMask, callback, url, userName, pwd) {
debugger;
var proxy = this;
proxy.CtlToMask = ctlToMask;
var client = new Sample.provider.SvcClient();
var params = {
Url: url,
HttpMethod: "GET",
Credentials: Sample.util.Conversions.Base64.encode(userName + ":" + pwd),
CtlToMask: proxy.CtlToMask,
Scope:proxy,
BeforeRequest: function(conn,o,result,Scope) {
debugger;
if(Scope.CtlToMask !=null) {
if(Scope.CtlToMask.getEl() != undefined)
Scope.CtlToMask.getEl().mask('Testing Connectivity...', 'x-mask-loading');
else
Scope.CtlToMask.mask('Testing Connectivity...', 'x-mask-loading');
}
},
RequestComplete: function(conn,o,result) {
if(this.CtlToMask !=null) {
if(this.CtlToMask.getEl() != undefined)
this.CtlToMask.getEl().unmask(true);
else
this.CtlToMask.unmask(true);
}
},
RequestException: function(conn,o,result) {
if(this.CtlToMask !=null) {
if(this.CtlToMask.getEl() != undefined)
this.CtlToMask.getEl().unmask(true);
else
this.CtlToMask.unmask(true);
}
}
};
client.TestConnectivity(params);
}
});
我的控制器如下所示:
Ext.define('Sample.controller.Locations', {
extend: 'Ext.app.Controller',
models: ['Location', 'Country'],
views: [
'portal.location.Menu',
'portal.location.Edit'
],
init: function() {
this.control({
'locationsMenu':{
OpenAddNewSvcPopup: this.OnOpenAddNewSvcPopup
},
'locationsEdit':{
TestSvcConnectivity: this.OnTestSvcConnectivity,
render: function () { },
afterrender: function () { },
boxready: function () { }
}
});
},
OnOpenAddNewSvcPopup: function(){
var newLoc = Ext.create('Sample.model.Location', {
UserName: 'admin',
Uri: 'http://localhost/DataServicesBase/Data.svc'
});
var v = Ext.create('widget.locationsEdit',{ mode:'add'});
v.down('form').loadRecord(newLoc);
},
OnTestSvcConnectivity: function(ctl){
var proxy = new Sample.util.ClientProxy();
proxy.DoTestConnection(
ctl,
this.OnTestSvcConnectivityCallback,
ctl.down("#Uri").value + '/Countries',
ctl.down("#UserName").value,
ctl.down("#Password").value
);
},
OnTestSvcConnectivityCallback: function(options,success,result){
if(success) {
//show the result
}
else {
//Show error in window
}
}
});
视图如下所示:
Ext.define('Sample.view.portal.location.Edit', {
extend: 'Ext.window.Window',
alias: 'widget.locationsEdit',
//title: 'Edit Service Location',
layout: 'fit',
autoShow: true,
title: 'Edit Service Location',
bodyStyle: 'border:0px',
closeAction:'destroy',
config:{
mode: 'edit'
},
constructor: function(configs){
this.callParent(arguments);
this.initConfig(configs);
if(this.mode == "add") this.setTitle('Add New Service Location');
},
initComponent: function() {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name: 'Id',
itemId: 'Id',
fieldLabel: 'Unique Name',
labelStyle: 'font-weight:bold',
allowBlank: false,
maxLength: 64,
width: 300
},
{
xtype: 'textfield',
name : 'Uri',
itemId: 'Uri',
fieldLabel: 'URI',
maxLength: 300,
width: 500,
allowBlank: false
},
{
xtype: 'textfield',
name : 'UserName',
itemId: 'UserName',
fieldLabel: 'User Name',
allowBlank: false,
maxLength: 64,
width: 200
},
{
xtype: 'textfield',
name : 'Password',
itemId: 'Password',
fieldLabel: 'Password',
allowBlank: false,
maxLength: 64,
width: 200
}
],
bodyStyle: 'padding:5px;'
}
];
this.buttons = [
{
text: 'Test Connectivity',
action: 'test',
scope: this,
handler: this.OnTestSvcConnectivity
},
{
text: 'Save',
action: 'save'
},
{
text: 'Cancel',
scope: this,
handler: this.close
}
];
this.callParent();
this.addEvents('TestSvcConnectivity') //custom event
},
OnTestSvcConnectivity: function(){
this.fireEvent('TestSvcConnectivity', this); //will be raised to controller
}
});
这种方法在我第一次点击"测试连接"按钮(来自弹出窗口)。如果我第二次单击相同的按钮,(BeforeRequest)处理程序将触发两次。第三次单击,处理程序被激活三次。我的代码中有什么错误。
如果我取消弹出窗口并再次单击"测试连接"它永远不会奏效。处理程序仍然保持"一些"上一个弹出窗口实例的引用(或状态)。由于无法找到,它会抛出" undefine"对象成员。我通过调试器确认了这一点,我可以看到前一个弹出窗口实例的id而不是当前的id。处理程序总是试图尊重第一个实例化的弹出窗口,无论如何。
我们为此示例原型试图遵循的模式是否存在任何陷阱/问题。我们正在尝试使用ExtJS的MVC功能进行开发,并确保我们使用支持和良好的模式/实践,这样我们就不会遇到上述非常基本的问题。