JavaScript、JQuery 和 JQWidgets 的奇怪执行
Weird execution of JavaScript, JQuery and JQWidgets
好的,...我在前端使用 JQuery v2.2.3,JQWidgets v4.1.2,在后端使用 ASP.NET MVC 5 我正在使用 ASP.NET c#.
我的页面类似于 SPA,因为它非常庞大。我遇到困难的部分是脚本应该使用同步 Ajax 调用重新填充我所有的 JQXGrids。我知道 Ajax 本来是异步的,但是当异步时 ajax 调用会忽略我的重复调用。这是应该发生的事情:
- 当最终用户从帐户下拉列表中选择新帐户时,脚本会关闭网格,清除选择并打开新帐户对话框。
- 帐户创建后,新帐户创建对话框关闭。
- (这是奇怪的地方) 然后脚本应该重新填充页面上的所有 JQXGrids 以反映添加。
- 最后,应该在创建帐户的下拉列表中自动选择创建的帐户。
这是脚本在当前状态下实际执行的操作:
- 当最终用户从帐户下拉列表中选择新帐户时,脚本会关闭网格,清除选择并打开新帐户对话框。
- 帐户创建后,新帐户创建对话框关闭。
- 脚本然后尝试重新填充页面上的所有 JQXGrids 以反映添加。
- 脚本在每个下拉菜单下方创建重复的下拉菜单。
- 创建的帐户会在创建帐户的下拉列表中自动选择。 However, when selected the grid ONLY shows that account, when the duplicate grids are selected, all accounts show up AND when the dialogue is closed, the dropdown grid that was clicked on (the duplicate)留在屏幕上。
这是我的 HTML/Razor 脚本部分,所有 JQXGrids 都仿照该部分:
<div class="col-sm-7">
<div id="jqxSubAccountDropdownButton">
<div id="jqxSubAccountDropdownWidget" style="font-size: 13px; font-family: Verdana; float: left;">
<div id="jqxSubAccountDropdownGrid"></div>
</div>
</div>
</div>
这是应该自动填充它启动序列的脚本部分:
function PopulateAccounts(rePopulate) {
PopulateAccountArray("jqxSubAccountDropdownGrid", F, null, null, rePopulate);
}
这是保存新帐户并返回记录 ID Guid 的脚本部分:
function SaveAccount(GridName) {
var rowIndex;
var AccountNumber = $("#txtNewAccountAccountNumber").val();
var AccountTypeID = $("#listAddNewAccountType").val();
var Balance = $("#txtEndingBalance").val();
var CurrencyReferenceListID = $("#listNewAccountCurrency").val();
var Description = $("#txtNewAccountDescription").val();
var Name = $("#txtAccountName").val();
var Note = $("#txtNewAccountNote").val();
var OpenBalance = $("#txtEndingBalance").val();
var OpenBalanceDate = $("#txtEndingDate").val();
var OrderChecksAt = $("#txtNewAccountOrderChecks").val();
var ParentID = $("#chkAddNewAccountSubAccount").val();
var RoutingNumber = $("#txtNewAccountRoutingNumber").val();
var TaxLineInfoReturnTaxLineID = $("#listNewAccountTaxLineMapping").val();
var _AccountData = {
"GridName": GridName,
"AccountData": {
"Name": Name,
"IsActive": T,
"ParentID": ParentID,
"AccountTypeID": AccountTypeID,
"SpecialAccountTypeID": null,
"IsTaxAccount": null,
"AccountNumber": AccountNumber,
"RoutingNumber": RoutingNumber,
"Description": Description,
"Note": Note,
"Balance": OpenBalance,
"TotalBalance": OpenBalance,
"OpenBalance": OpenBalance,
"OpenBalanceDate": OpenBalanceDate,
"TaxLineInfoReturnTaxLineID": TaxLineInfoReturnTaxLineID,
"CashFlowClassification": null,
"CurrencyReferenceListID": CurrencyReferenceListID,
"OrderChecksAt": OrderChecksAt
}
};
callService("POST", g_WebServiceSaveAccountURL, _AccountData, function (jsonData) {
alert("Record Added");
PopulateAccounts(true);
rowIndex = GetRowIDOfItemByGUID(GridName, jsonData.AccountID, "AccountIndex");
$("#" + GridName).jqxGrid('selectrow', rowIndex);
});
}
这是应该创建网格并分配事件绑定的脚本部分:
function AccountsMulticolumn(GridName, data, rePopulate) {
var _Object = $("#" + GridName);
var _ObjectParent = _Object.parent();
var _ObjectParentParent = _Object.parent().parent();
// if (rePopulate) {
// _Object.remove();
// _ObjectParent.append("<div id='" + GridName + "'></div>")
// }
var source = { localdata: data, datatype: "array" };
$(_ObjectParentParent).jqxDropDownButton({ width: 150, height: 25 });
$(_Object).jqxGrid({
width: 550,
height: 200,
source: source,
theme: 'energyblue',
columns: [
{ text: '', datafield: 'AccountIndex', width: 0 },
{ text: 'Account Name', datafield: 'AccountName', width: 300 },
{ text: 'Account Type', datafield: 'AccountType', width: 200 }
]
});
$(_Object).jqxGrid('selectionmode', 'singlerow');
$(_Object).bind('rowselect', function (event) {
var args = event.args;
var row = $(_Object).jqxGrid('getrowdata', args.rowindex);
if (row["AccountName"].toString().toLowerCase() !== "new") {
var dropDownContent = '<div style="position: relative; margin-left: 3px; margin-top: 5px;">' + row["AccountName"] + '</div>';
_ObjectParentParent.jqxDropDownButton('close');
}
$(_ObjectParentParent).jqxDropDownButton('setContent', dropDownContent);
if (row["AccountName"].toString().toLowerCase() === "new") {
_ObjectParentParent.jqxDropDownButton('close');
$("#divNewAccountDetails").dialog("open");
$(_Object).jqxGrid('clearselection');
g_JQXGridName = GridName;
}
});
}
这是从 API 获取数据并将其解析为 JQXGrid 函数可用格式的脚本部分:
function PopulateAccountArray(GridName, ShowNew, rePopulate) {
callService("GET", g_WebServiceAccountsGetAllSpecialURL, null, function (jsonResult) {
var data = new Array();
var AccountIndex_Default = [""];
var AccountName_Default = [""];
var AccountNotes_Default = [""];
if (ShowNew) {
AccountName_Default = ["New"];
}
var _oAccountID = [];
var _oAccountName = [];
var _oAccountNotes = [];
if (jsonResult.length > 0) {
for (i = 0; i < jsonResult.length; i++) {
_oAccountID[i] = jsonResult[i].RecordID;
_oAccountName[i] = jsonResult[i].AccountName;
_oAccountNotes[i] = jsonResult[i].AccountType;
};
var AccountIndex_FromService = _oAccountID;
var AccountName_FromService = _oAccountName;
var AccountType_FromService = _oAccountNotes;
var AccountIndex = AccountIndex_Default.concat(AccountIndex_FromService);
var AccountName = AccountName_Default.concat(AccountName_FromService);
var AccountType = AccountNotes_Default.concat(AccountType_FromService);
} else {
var AccountIndex = AccountIndex_Default;
var AccountName = AccountName_Default;
var AccountType = AccountNotes_Default;
}
for (var i = 0; i < AccountIndex.length; i++) {
var row = {};
row["AccountIndex"] = AccountIndex[i];
row["AccountName"] = AccountName[i];
row["AccountType"] = AccountType[i];
data[i] = row;
}
AccountsMulticolumn(GridName, data, rePopulate);
});
}
最后是我的 AJAX 电话:
function callService(Type, Url, Data, successFunction) {
$.ajax({
type: Type, // GET or POST or PUT or DELETE verb
dataType: "json",
async: false,
url: Url, // Location of the service
data: Data, // Data sent to server
success: successFunction,
error: serviceErrorHandler // When Service call fails
});
}
原来,我是自己最大的敌人。我意识到函数调用位置几乎 重要 。因此,在完全重写我的函数、mvc razor 代码放置、确保我在 AJAX 调用中使用同步调用并重新指定 JQ Widget 网格的网格数据之后,所有问题都得到了解决。
好的,...我在前端使用 JQuery v2.2.3,JQWidgets v4.1.2,在后端使用 ASP.NET MVC 5 我正在使用 ASP.NET c#.
我的页面类似于 SPA,因为它非常庞大。我遇到困难的部分是脚本应该使用同步 Ajax 调用重新填充我所有的 JQXGrids。我知道 Ajax 本来是异步的,但是当异步时 ajax 调用会忽略我的重复调用。这是应该发生的事情:
- 当最终用户从帐户下拉列表中选择新帐户时,脚本会关闭网格,清除选择并打开新帐户对话框。
- 帐户创建后,新帐户创建对话框关闭。
- (这是奇怪的地方) 然后脚本应该重新填充页面上的所有 JQXGrids 以反映添加。
- 最后,应该在创建帐户的下拉列表中自动选择创建的帐户。
这是脚本在当前状态下实际执行的操作:
- 当最终用户从帐户下拉列表中选择新帐户时,脚本会关闭网格,清除选择并打开新帐户对话框。
- 帐户创建后,新帐户创建对话框关闭。
- 脚本然后尝试重新填充页面上的所有 JQXGrids 以反映添加。
- 脚本在每个下拉菜单下方创建重复的下拉菜单。
- 创建的帐户会在创建帐户的下拉列表中自动选择。 However, when selected the grid ONLY shows that account, when the duplicate grids are selected, all accounts show up AND when the dialogue is closed, the dropdown grid that was clicked on (the duplicate)留在屏幕上。
这是我的 HTML/Razor 脚本部分,所有 JQXGrids 都仿照该部分:
<div class="col-sm-7">
<div id="jqxSubAccountDropdownButton">
<div id="jqxSubAccountDropdownWidget" style="font-size: 13px; font-family: Verdana; float: left;">
<div id="jqxSubAccountDropdownGrid"></div>
</div>
</div>
</div>
这是应该自动填充它启动序列的脚本部分:
function PopulateAccounts(rePopulate) {
PopulateAccountArray("jqxSubAccountDropdownGrid", F, null, null, rePopulate);
}
这是保存新帐户并返回记录 ID Guid 的脚本部分:
function SaveAccount(GridName) {
var rowIndex;
var AccountNumber = $("#txtNewAccountAccountNumber").val();
var AccountTypeID = $("#listAddNewAccountType").val();
var Balance = $("#txtEndingBalance").val();
var CurrencyReferenceListID = $("#listNewAccountCurrency").val();
var Description = $("#txtNewAccountDescription").val();
var Name = $("#txtAccountName").val();
var Note = $("#txtNewAccountNote").val();
var OpenBalance = $("#txtEndingBalance").val();
var OpenBalanceDate = $("#txtEndingDate").val();
var OrderChecksAt = $("#txtNewAccountOrderChecks").val();
var ParentID = $("#chkAddNewAccountSubAccount").val();
var RoutingNumber = $("#txtNewAccountRoutingNumber").val();
var TaxLineInfoReturnTaxLineID = $("#listNewAccountTaxLineMapping").val();
var _AccountData = {
"GridName": GridName,
"AccountData": {
"Name": Name,
"IsActive": T,
"ParentID": ParentID,
"AccountTypeID": AccountTypeID,
"SpecialAccountTypeID": null,
"IsTaxAccount": null,
"AccountNumber": AccountNumber,
"RoutingNumber": RoutingNumber,
"Description": Description,
"Note": Note,
"Balance": OpenBalance,
"TotalBalance": OpenBalance,
"OpenBalance": OpenBalance,
"OpenBalanceDate": OpenBalanceDate,
"TaxLineInfoReturnTaxLineID": TaxLineInfoReturnTaxLineID,
"CashFlowClassification": null,
"CurrencyReferenceListID": CurrencyReferenceListID,
"OrderChecksAt": OrderChecksAt
}
};
callService("POST", g_WebServiceSaveAccountURL, _AccountData, function (jsonData) {
alert("Record Added");
PopulateAccounts(true);
rowIndex = GetRowIDOfItemByGUID(GridName, jsonData.AccountID, "AccountIndex");
$("#" + GridName).jqxGrid('selectrow', rowIndex);
});
}
这是应该创建网格并分配事件绑定的脚本部分:
function AccountsMulticolumn(GridName, data, rePopulate) {
var _Object = $("#" + GridName);
var _ObjectParent = _Object.parent();
var _ObjectParentParent = _Object.parent().parent();
// if (rePopulate) {
// _Object.remove();
// _ObjectParent.append("<div id='" + GridName + "'></div>")
// }
var source = { localdata: data, datatype: "array" };
$(_ObjectParentParent).jqxDropDownButton({ width: 150, height: 25 });
$(_Object).jqxGrid({
width: 550,
height: 200,
source: source,
theme: 'energyblue',
columns: [
{ text: '', datafield: 'AccountIndex', width: 0 },
{ text: 'Account Name', datafield: 'AccountName', width: 300 },
{ text: 'Account Type', datafield: 'AccountType', width: 200 }
]
});
$(_Object).jqxGrid('selectionmode', 'singlerow');
$(_Object).bind('rowselect', function (event) {
var args = event.args;
var row = $(_Object).jqxGrid('getrowdata', args.rowindex);
if (row["AccountName"].toString().toLowerCase() !== "new") {
var dropDownContent = '<div style="position: relative; margin-left: 3px; margin-top: 5px;">' + row["AccountName"] + '</div>';
_ObjectParentParent.jqxDropDownButton('close');
}
$(_ObjectParentParent).jqxDropDownButton('setContent', dropDownContent);
if (row["AccountName"].toString().toLowerCase() === "new") {
_ObjectParentParent.jqxDropDownButton('close');
$("#divNewAccountDetails").dialog("open");
$(_Object).jqxGrid('clearselection');
g_JQXGridName = GridName;
}
});
}
这是从 API 获取数据并将其解析为 JQXGrid 函数可用格式的脚本部分:
function PopulateAccountArray(GridName, ShowNew, rePopulate) {
callService("GET", g_WebServiceAccountsGetAllSpecialURL, null, function (jsonResult) {
var data = new Array();
var AccountIndex_Default = [""];
var AccountName_Default = [""];
var AccountNotes_Default = [""];
if (ShowNew) {
AccountName_Default = ["New"];
}
var _oAccountID = [];
var _oAccountName = [];
var _oAccountNotes = [];
if (jsonResult.length > 0) {
for (i = 0; i < jsonResult.length; i++) {
_oAccountID[i] = jsonResult[i].RecordID;
_oAccountName[i] = jsonResult[i].AccountName;
_oAccountNotes[i] = jsonResult[i].AccountType;
};
var AccountIndex_FromService = _oAccountID;
var AccountName_FromService = _oAccountName;
var AccountType_FromService = _oAccountNotes;
var AccountIndex = AccountIndex_Default.concat(AccountIndex_FromService);
var AccountName = AccountName_Default.concat(AccountName_FromService);
var AccountType = AccountNotes_Default.concat(AccountType_FromService);
} else {
var AccountIndex = AccountIndex_Default;
var AccountName = AccountName_Default;
var AccountType = AccountNotes_Default;
}
for (var i = 0; i < AccountIndex.length; i++) {
var row = {};
row["AccountIndex"] = AccountIndex[i];
row["AccountName"] = AccountName[i];
row["AccountType"] = AccountType[i];
data[i] = row;
}
AccountsMulticolumn(GridName, data, rePopulate);
});
}
最后是我的 AJAX 电话:
function callService(Type, Url, Data, successFunction) {
$.ajax({
type: Type, // GET or POST or PUT or DELETE verb
dataType: "json",
async: false,
url: Url, // Location of the service
data: Data, // Data sent to server
success: successFunction,
error: serviceErrorHandler // When Service call fails
});
}
原来,我是自己最大的敌人。我意识到函数调用位置几乎 重要 。因此,在完全重写我的函数、mvc razor 代码放置、确保我在 AJAX 调用中使用同步调用并重新指定 JQ Widget 网格的网格数据之后,所有问题都得到了解决。