为什么当我编辑同一行中的另一个单元格时,此数据 table 单元格恢复为旧值?
Whys is this data table cell reverting to old value when I edit another cell in the same row?
我正在使用以前的开发人员设置的 jQuery 数据 table。对于 editable 的列,每当您双击值、更改它并点击 return 时,数据库 table 中的相应记录将通过 AJAX 更新.但是数据中的一个字段 table 似乎总是在发生这种情况时恢复为较旧的显然已存储的值。
此列是一条错误消息。发生的情况是,数据 table 最初是从数据库查询填充的,该查询获取的记录在提交时验证失败。所以可能电子邮件地址无效,数据 table 将向您显示记录,以及错误的电子邮件地址,以及来自 API 的错误消息“错误的电子邮件地址”。因此,您通过双击、更改并点击 return 来更新电子邮件地址。这会更新数据库中暂存 table 中的记录,现在可以将其重新提交到 API.
我设置了一个按钮和一个 jQuery 功能来重新提交到 API。因此,您单击该按钮,然后拉取并提交该 DB staging table 中更正的记录。但是说记录还有另一个问题,比如 SSN 无效。 API 将捕获它并回复一条新的错误消息,我的函数捕获 API 的响应并相应地更新数据库暂存 table 和数据 table。现在在屏幕上您会看到更新了该行的数据 table;它有一条新的错误消息,我的函数在 <td>
元素中使用 $('#errorMessageTD').text(newErrorMessageFromAPI)
.
更改了它
这就是问题所在 - 现在,如果您双击进入 SSN 值,将其更改为有效的 SSN,然后点击 return,那么旧的“无效电子邮件地址”消息会立即替换 SSN <td>
中的错误消息。在 DB staging table 中,错误消息保留为 SSN 错误消息,因此不会从那里提取值。所以我认为必须发生的事情是,使用上面的 text() 函数替换用户在 <td>
元素中看到的错误消息,但不会替换 jQuery 数据 table 已存储该列和行。或者,并不是该值本身存储在数据 table 中,而是显然该值存储在某处。因此,当您编辑该行中的另一个单元格并点击 return 时,<td>
的内容将替换为 table 首次呈现到屏幕时的原始文本。
所以我想知道的是,当编辑字段并按下回车按钮时,如何让新的错误消息保留在 td
中?为什么这个 <td>
会恢复原状,而该行中的所有其他 <td>
都保持不变,即使它们已经过编辑?
相关代码如下。在这种情况下,错误消息列是 aoColumnDefs 中的列 [0],而不是 editable 字段。此数据 table 最初是从暂存数据库 table 的查询中填充的,并且似乎是 <td>
返回到每当您按 Enter 键编辑其中的字段时的初始值同一行。
// Data Table Scripts for Mass Uploader
var oTable;
var editRowID;
var editText;
$(document).ready(function() {
$('#myTable').dataTable({
// Set the column names for saving to the database
// The number of these settings need to be the same as the number of TRs and TDs in the table
"aoColumnDefs": [
{"sWidth": "150px", "aTargets":[0]},
{"sWidth": "60px","sName": "appl_fname", "aTargets":[1]},
{"sWidth": "50px","sName": "appl_mname","aTargets":[2]},
{"sWidth": "70px","sName": "appl_lname","aTargets":[3]},
{"sWidth": "75px","sName": "appl_street","aTargets":[4]},
{"sWidth": "60px","sName": "appl_street2","aTargets":[5]},
{"sWidth": "60px","sName": "appl_city","aTargets":[6]},
{"sWidth": "45px","sName": "appl_state","aTargets":[7]},
{"sWidth": "45px","sName": "appl_zip","aTargets":[8]},
{"sWidth": "80px","sName": "appl_dob","aTargets":[9]},
{"sWidth": "80px","sName": "appl_ssn","aTargets":[10]},
{"sWidth": "80px","sName": "appl_phone","aTargets":[11]},
{"sWidth": "120px","sName": "appl_email_box","aTargets":[12]},
{"sWidth": "120px","aTargets":[13]},
{"sWidth": "120px","aTargets":[14]},
{"sWidth": "120px","aTargets":[15]},
{"sWidth": "50px","sName": "job_id","aTargets":[16]},
{"sWidth": "80px","sName": "start_date","aTargets":[17]},
{"sWidth": "60px","sName": "pay_rate","aTargets":[18]},
{"sWidth": "70px","sName": "base_salary","aTargets":[19]},
{"sWidth": "70px","sName": "position_type","aTargets":[20]},
{"sWidth": "100px","sName": "benefit_status","aTargets":[21]},
{"sWidth": "80px","sName": "status","aTargets":[22]},
{"sWidth": "80px","sName": "reportsToRecLoginId","aTargets":[23]},
{"sWidth": "80px","sName": "Send_Welcome_Email","aTargets":[24]},
{"sWidth": "80px","sName": "Stage_To_Save_To_ID","aTargets":[25]},
{"sWidth": "120px","aTargets":["SSCustomField"]}
],
//"sPaginationType": "full_numbers"
"sScrollXInner": "120%",
"bPaginate": false,
"bAutoWidth": false,
"bScrollCollapse": false,
"bAutoWidth": false,
"bFilter": false
}).makeEditable({
// Set what columns are editable
// The number of these settings need to be the same as the number of TRs and TDs in the table
"aoColumns": [
null,
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
null,
null,
null,
{},
{},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Per Hour','2':'Per Year'}",
event: 'dblclick'},
{},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Full Time','2':'Part Time','-1':'Other'}",
event: 'dblclick'},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Full Company Benefits','2':'Employee Contribution Benefits','3':'Employee Paid Benefits','4':'No Benefits','-1':'Other'}",
event: 'dblclick'},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Exempt','2':'Non-Exempt','-1':'Other'}",
event: 'dblclick'},
/*{},*/
null,//make ReportsTo not editable
null,//make Send Welcome Email not editable
/*{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', 'true':'Yes','false':'No'}",
event: 'dblclick'},*/
/*{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '9':'Completed','8':'Onboarding'}",
event: 'dblclick'},*/
null,//make Status to Save To Not Editable
{}
/*{}*/
],
fnOnDeleted: function(status) {
oTable.fnDraw();
},
fnOnEditing: function(input, oEditableSettings, sOriginalText, id) {
editRowID = id;
editText = sOriginalText;
return true;
},
fnOnEdited: function(status, sOldValue, sNewCellDisplayValue, aPos0, aPos1, aPos2) {
if(aPos2 == 16 && editText == sOldValue && sNewCellDisplayValue.trim() != '') {
$.ajax({
url: "Admin/MassUpload/GetLocationDepartmentPosition.cfm",
type: "POST",
dataType: "json",
data: {JobID: sNewCellDisplayValue, ErrorRowID: editRowID},
success: function (data) {
var stringData = data.DATA.toString();
if (stringData.length > 0) {
var locationPosition, departmentPosition, positionPosition;
locationPosition = 'Row'+editRowID+'Location';
$('#'+locationPosition).text(data.DATA[0][4]);
departmentPosition = 'Row'+editRowID+'Department';
$('#'+departmentPosition).text(data.DATA[0][2]);
positionPosition = 'Row'+editRowID+'Position';
$('#'+positionPosition).text(data.DATA[0][6]);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(thrownError);
}
});
}
},
sUpdateURL: "Admin/MassUpload/UpdateDataTableRow.cfm",
sDeleteURL: "Admin/MassUpload/DeleteDataTableRow.cfm"
});
$('#demo').submit( function() {
var sData = $('input', oTable.fnGetNodes()).serialize();
this.submit();
return false;
});
/* Add a click handler to the rows - this could be used as a callback */
$("#example tbody tr").click( function( e ) {
if ( $(this).hasClass('row_selected') ) {
$(this).removeClass('row_selected');
} else {
oTable.$('tr.row_selected').removeClass('row_selected');
$(this).addClass('row_selected');
}
});
/* Add a click handler for the delete row */
$('#delete').click( function() {
var anSelected = fnGetSelected( oTable );
oTable.fnDeleteRow( anSelected[0] );
});
oTable = $('#myTable').dataTable();
setTimeout(function(){
oTable.fnAdjustColumnSizing();
},100);
});
此外,下面是我编写的函数,用于将更正的错误重新提交给 API,并使用来自 API 的新错误消息更新 td:
processData = function() {
$.ajax({
url: "Admin/MassUpload/processErrorsThroughAPI.cfm",
type: "POST",
dataType: "json",
success: function (data) {
console.log("data stringified: " + JSON.stringify(data));
if (data.length > 0) {//There are rows in the table to delete or error messages to update
$.each(data, function(index, item){
if (item.ERRORMESSAGE == "") {//Record passed validation. Remove this row from the data table.
oTable.fnDeleteRow($('#'+item.IMPORTERRORID)[0]);
oTable.fnDraw();
}
else {//Record did not pass validation, display new error message in the data table
$('#Row'+item.IMPORTERRORID+'ErrorMsg').text(item.ERRORMESSAGE);
}
//console.log(index);
console.log("item.IMPORTERRORID = " + item.IMPORTERRORID);
console.log("item.ERRORMESSAGE = " + item.ERRORMESSAGE);
});
}
else {//No items to process, so nothing to display
var divInfo = '<div class="container-fluid"> <div class="row-fluid"> <div class="well well-clear span6 offset3">';
divInfo += 'Any errors associated with the uploading of the spreadsheet have been corrected.<br/>';
divInfo += '<button type="button" onclick="selectExcelFile()">Go back to hire import</button><br/>';
divInfo += '</div> </div> </div>';
$('#hireImportTab').html(divInfo);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(thrownError);
}
});
}
好的,在完全被难住了几周之后,这里是解决方法。
首先,使此数据 Table editable 的代码似乎来自 GitHub - https://github.com/ansballard/jquery-datatables-editable.
上的一个分支
其次,post 中描述的不良行为似乎是固有的。对于 table 中的给定行,您可以使用 jQuery:
更改 td 元素的文本
$('#myTDCell_row1').text('Here is some new text');
但在那之后,如果您通过双击单元格的内容编辑该 td 同一行中的任何其他单元格,输入新内容,然后按“输入”键,该单元格的文本将恢复为原来的样子之前。
我不确定这是为什么,但幸运的是,在您定义数据的 jQuery 代码中 Table,数据 Table 对象的一个函数名为“ makeEditable()”,并且在该函数中还有几个其他可选函数,“fnOnEditing()”和“fnOnEdited()”。这些函数可用于在 td 单元格中保留新文本。
我所做的是首先定义一个全局变量,这样就可以在单元格文本更改之前捕获新文本并将其存储在 fnOnEditing() 中,然后在 fnOnEdited() 中可以检索并放置它返回该单元格的文本。
请参阅下面的代码了解总体思路。
//define global variables
var latestText;
var editRowID;
$(document).ready(function() {
$('#myTable').dataTable({
[ColumnDefs, other config options]
}).makeEditable({
[settings for if/how each column can be edited],
fnOnEditing: function(input, oEditableSettings, sOriginalText, id) {
//this function is run right before the edit is executed
//capture the edited row's id and the text in the cell
editRowID = id;
latestText = $('#myTDCell_row' + editRowID).text();
},
fnOnEdited: function(status, sOldValue, sNewCellDisplayValue, aPos0, aPos1, aPos2) {
//this function runs after the edit has been made
/* the edit has been made to some cell in the row, and the text in our cell (which is another cell in that same row) has reverted to what it was before we changed it. So now we immediately change it back */
$('#myTDCell_row' + editRowID).text(latestText);
},
sUpdateURL: [path to page that handles the actual back-end DB update; a request is made to this page as soon as you click the enter key]
});
我正在使用以前的开发人员设置的 jQuery 数据 table。对于 editable 的列,每当您双击值、更改它并点击 return 时,数据库 table 中的相应记录将通过 AJAX 更新.但是数据中的一个字段 table 似乎总是在发生这种情况时恢复为较旧的显然已存储的值。
此列是一条错误消息。发生的情况是,数据 table 最初是从数据库查询填充的,该查询获取的记录在提交时验证失败。所以可能电子邮件地址无效,数据 table 将向您显示记录,以及错误的电子邮件地址,以及来自 API 的错误消息“错误的电子邮件地址”。因此,您通过双击、更改并点击 return 来更新电子邮件地址。这会更新数据库中暂存 table 中的记录,现在可以将其重新提交到 API.
我设置了一个按钮和一个 jQuery 功能来重新提交到 API。因此,您单击该按钮,然后拉取并提交该 DB staging table 中更正的记录。但是说记录还有另一个问题,比如 SSN 无效。 API 将捕获它并回复一条新的错误消息,我的函数捕获 API 的响应并相应地更新数据库暂存 table 和数据 table。现在在屏幕上您会看到更新了该行的数据 table;它有一条新的错误消息,我的函数在 <td>
元素中使用 $('#errorMessageTD').text(newErrorMessageFromAPI)
.
这就是问题所在 - 现在,如果您双击进入 SSN 值,将其更改为有效的 SSN,然后点击 return,那么旧的“无效电子邮件地址”消息会立即替换 SSN <td>
中的错误消息。在 DB staging table 中,错误消息保留为 SSN 错误消息,因此不会从那里提取值。所以我认为必须发生的事情是,使用上面的 text() 函数替换用户在 <td>
元素中看到的错误消息,但不会替换 jQuery 数据 table 已存储该列和行。或者,并不是该值本身存储在数据 table 中,而是显然该值存储在某处。因此,当您编辑该行中的另一个单元格并点击 return 时,<td>
的内容将替换为 table 首次呈现到屏幕时的原始文本。
所以我想知道的是,当编辑字段并按下回车按钮时,如何让新的错误消息保留在 td
中?为什么这个 <td>
会恢复原状,而该行中的所有其他 <td>
都保持不变,即使它们已经过编辑?
相关代码如下。在这种情况下,错误消息列是 aoColumnDefs 中的列 [0],而不是 editable 字段。此数据 table 最初是从暂存数据库 table 的查询中填充的,并且似乎是 <td>
返回到每当您按 Enter 键编辑其中的字段时的初始值同一行。
// Data Table Scripts for Mass Uploader
var oTable;
var editRowID;
var editText;
$(document).ready(function() {
$('#myTable').dataTable({
// Set the column names for saving to the database
// The number of these settings need to be the same as the number of TRs and TDs in the table
"aoColumnDefs": [
{"sWidth": "150px", "aTargets":[0]},
{"sWidth": "60px","sName": "appl_fname", "aTargets":[1]},
{"sWidth": "50px","sName": "appl_mname","aTargets":[2]},
{"sWidth": "70px","sName": "appl_lname","aTargets":[3]},
{"sWidth": "75px","sName": "appl_street","aTargets":[4]},
{"sWidth": "60px","sName": "appl_street2","aTargets":[5]},
{"sWidth": "60px","sName": "appl_city","aTargets":[6]},
{"sWidth": "45px","sName": "appl_state","aTargets":[7]},
{"sWidth": "45px","sName": "appl_zip","aTargets":[8]},
{"sWidth": "80px","sName": "appl_dob","aTargets":[9]},
{"sWidth": "80px","sName": "appl_ssn","aTargets":[10]},
{"sWidth": "80px","sName": "appl_phone","aTargets":[11]},
{"sWidth": "120px","sName": "appl_email_box","aTargets":[12]},
{"sWidth": "120px","aTargets":[13]},
{"sWidth": "120px","aTargets":[14]},
{"sWidth": "120px","aTargets":[15]},
{"sWidth": "50px","sName": "job_id","aTargets":[16]},
{"sWidth": "80px","sName": "start_date","aTargets":[17]},
{"sWidth": "60px","sName": "pay_rate","aTargets":[18]},
{"sWidth": "70px","sName": "base_salary","aTargets":[19]},
{"sWidth": "70px","sName": "position_type","aTargets":[20]},
{"sWidth": "100px","sName": "benefit_status","aTargets":[21]},
{"sWidth": "80px","sName": "status","aTargets":[22]},
{"sWidth": "80px","sName": "reportsToRecLoginId","aTargets":[23]},
{"sWidth": "80px","sName": "Send_Welcome_Email","aTargets":[24]},
{"sWidth": "80px","sName": "Stage_To_Save_To_ID","aTargets":[25]},
{"sWidth": "120px","aTargets":["SSCustomField"]}
],
//"sPaginationType": "full_numbers"
"sScrollXInner": "120%",
"bPaginate": false,
"bAutoWidth": false,
"bScrollCollapse": false,
"bAutoWidth": false,
"bFilter": false
}).makeEditable({
// Set what columns are editable
// The number of these settings need to be the same as the number of TRs and TDs in the table
"aoColumns": [
null,
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
null,
null,
null,
{},
{},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Per Hour','2':'Per Year'}",
event: 'dblclick'},
{},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Full Time','2':'Part Time','-1':'Other'}",
event: 'dblclick'},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Full Company Benefits','2':'Employee Contribution Benefits','3':'Employee Paid Benefits','4':'No Benefits','-1':'Other'}",
event: 'dblclick'},
{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '1':'Exempt','2':'Non-Exempt','-1':'Other'}",
event: 'dblclick'},
/*{},*/
null,//make ReportsTo not editable
null,//make Send Welcome Email not editable
/*{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', 'true':'Yes','false':'No'}",
event: 'dblclick'},*/
/*{type: 'select',
onblur: 'submit',
data: "{'':'Please select...', '9':'Completed','8':'Onboarding'}",
event: 'dblclick'},*/
null,//make Status to Save To Not Editable
{}
/*{}*/
],
fnOnDeleted: function(status) {
oTable.fnDraw();
},
fnOnEditing: function(input, oEditableSettings, sOriginalText, id) {
editRowID = id;
editText = sOriginalText;
return true;
},
fnOnEdited: function(status, sOldValue, sNewCellDisplayValue, aPos0, aPos1, aPos2) {
if(aPos2 == 16 && editText == sOldValue && sNewCellDisplayValue.trim() != '') {
$.ajax({
url: "Admin/MassUpload/GetLocationDepartmentPosition.cfm",
type: "POST",
dataType: "json",
data: {JobID: sNewCellDisplayValue, ErrorRowID: editRowID},
success: function (data) {
var stringData = data.DATA.toString();
if (stringData.length > 0) {
var locationPosition, departmentPosition, positionPosition;
locationPosition = 'Row'+editRowID+'Location';
$('#'+locationPosition).text(data.DATA[0][4]);
departmentPosition = 'Row'+editRowID+'Department';
$('#'+departmentPosition).text(data.DATA[0][2]);
positionPosition = 'Row'+editRowID+'Position';
$('#'+positionPosition).text(data.DATA[0][6]);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(thrownError);
}
});
}
},
sUpdateURL: "Admin/MassUpload/UpdateDataTableRow.cfm",
sDeleteURL: "Admin/MassUpload/DeleteDataTableRow.cfm"
});
$('#demo').submit( function() {
var sData = $('input', oTable.fnGetNodes()).serialize();
this.submit();
return false;
});
/* Add a click handler to the rows - this could be used as a callback */
$("#example tbody tr").click( function( e ) {
if ( $(this).hasClass('row_selected') ) {
$(this).removeClass('row_selected');
} else {
oTable.$('tr.row_selected').removeClass('row_selected');
$(this).addClass('row_selected');
}
});
/* Add a click handler for the delete row */
$('#delete').click( function() {
var anSelected = fnGetSelected( oTable );
oTable.fnDeleteRow( anSelected[0] );
});
oTable = $('#myTable').dataTable();
setTimeout(function(){
oTable.fnAdjustColumnSizing();
},100);
});
此外,下面是我编写的函数,用于将更正的错误重新提交给 API,并使用来自 API 的新错误消息更新 td:
processData = function() {
$.ajax({
url: "Admin/MassUpload/processErrorsThroughAPI.cfm",
type: "POST",
dataType: "json",
success: function (data) {
console.log("data stringified: " + JSON.stringify(data));
if (data.length > 0) {//There are rows in the table to delete or error messages to update
$.each(data, function(index, item){
if (item.ERRORMESSAGE == "") {//Record passed validation. Remove this row from the data table.
oTable.fnDeleteRow($('#'+item.IMPORTERRORID)[0]);
oTable.fnDraw();
}
else {//Record did not pass validation, display new error message in the data table
$('#Row'+item.IMPORTERRORID+'ErrorMsg').text(item.ERRORMESSAGE);
}
//console.log(index);
console.log("item.IMPORTERRORID = " + item.IMPORTERRORID);
console.log("item.ERRORMESSAGE = " + item.ERRORMESSAGE);
});
}
else {//No items to process, so nothing to display
var divInfo = '<div class="container-fluid"> <div class="row-fluid"> <div class="well well-clear span6 offset3">';
divInfo += 'Any errors associated with the uploading of the spreadsheet have been corrected.<br/>';
divInfo += '<button type="button" onclick="selectExcelFile()">Go back to hire import</button><br/>';
divInfo += '</div> </div> </div>';
$('#hireImportTab').html(divInfo);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(thrownError);
}
});
}
好的,在完全被难住了几周之后,这里是解决方法。
首先,使此数据 Table editable 的代码似乎来自 GitHub - https://github.com/ansballard/jquery-datatables-editable.
上的一个分支其次,post 中描述的不良行为似乎是固有的。对于 table 中的给定行,您可以使用 jQuery:
更改 td 元素的文本$('#myTDCell_row1').text('Here is some new text');
但在那之后,如果您通过双击单元格的内容编辑该 td 同一行中的任何其他单元格,输入新内容,然后按“输入”键,该单元格的文本将恢复为原来的样子之前。
我不确定这是为什么,但幸运的是,在您定义数据的 jQuery 代码中 Table,数据 Table 对象的一个函数名为“ makeEditable()”,并且在该函数中还有几个其他可选函数,“fnOnEditing()”和“fnOnEdited()”。这些函数可用于在 td 单元格中保留新文本。
我所做的是首先定义一个全局变量,这样就可以在单元格文本更改之前捕获新文本并将其存储在 fnOnEditing() 中,然后在 fnOnEdited() 中可以检索并放置它返回该单元格的文本。
请参阅下面的代码了解总体思路。
//define global variables
var latestText;
var editRowID;
$(document).ready(function() {
$('#myTable').dataTable({
[ColumnDefs, other config options]
}).makeEditable({
[settings for if/how each column can be edited],
fnOnEditing: function(input, oEditableSettings, sOriginalText, id) {
//this function is run right before the edit is executed
//capture the edited row's id and the text in the cell
editRowID = id;
latestText = $('#myTDCell_row' + editRowID).text();
},
fnOnEdited: function(status, sOldValue, sNewCellDisplayValue, aPos0, aPos1, aPos2) {
//this function runs after the edit has been made
/* the edit has been made to some cell in the row, and the text in our cell (which is another cell in that same row) has reverted to what it was before we changed it. So now we immediately change it back */
$('#myTDCell_row' + editRowID).text(latestText);
},
sUpdateURL: [path to page that handles the actual back-end DB update; a request is made to this page as soon as you click the enter key]
});