5

我正在使用 Spring、jsp、javascript、jquery 开发一个 webapp。

我使用数据表显示一个表格。当我单击表格行时,我希望它将所有字段更改为内联编辑输入、选择等。此外,我想在下一行显示一些额外的输入字段和一个保存按钮。

现在我看到了几种方法。我不确定该拿哪一个。

  1. 我可以获得所选行的句柄,然后遍历 td 并将它们转换为输入/选择字段。然后我可以为新字段和保存按钮插入一个额外的行。我不认为这是一个干净的解决方案。我将不得不手动发布一个帖子,而不是使用表单的 Spring ModelAttribute 绑定。(我还能在这里使用 ModelAttribute 吗?)

  2. 我可以在 jsp 文件中创建一个编辑表单,如下所示:

    <form:form action="" commandName=""> <td> <input ... > </td> <td> <select ... > </td> </tr> <tr> <td> <label> <input new field> </td> <td> <button> </td> </tr>

注意我在 jsp 文件中没有开头,因为我计划重用表中现有行中的 tr。这样我就可以拥有一个干净的表单,并且还可以使用我已经编写的将表单绑定到 Java 类的更新方法。此外,我不必担心输入字段与列名的对齐。

生成的 html 看起来像...

这种方法的问题是在 html 中放置表单元素会导致整个表单被限制在表格的一个单元格中,这看起来不太好并且弄乱了整个布局。有出路吗?我是否应该将表的内容替换为具有 colspan 的内容,然后将 div 放入此元素中并微调 css 以确保输入字段与表中的列名对齐?

显示错误对齐的图像

您可以提出更好的解决方案吗?如果问题不是很清楚,我可以填写更多详细信息。

4

6 回答 6

3

这就是我要做的(来自服务器端开发背景,因为我知道开发人员喜欢简单的解决方案)

  1. 用一个表格包裹表格
  2. 在编辑行(单击行)上打开一个 ajax 请求,该请求返回看起来像精确 tr 的纯 html,只有您想要包含的任何额外内容:

<tr><td><input type="text" name="text1" ... /></td><td>second row... </td></tr>
<tr><td colspan="2">And hey, here is more, and the save button ... </td></tr>  

  1. 在 jQuery 中,将 tr 替换为检索到的内容(myTr.replace($(ajaxResponse)))或类似内容

  2. 现在保存按钮是表单的常规提交

  3. 如果你想通过 ajax 提交,一旦完成,在你的 ajax 响应中返回旧的 html 并用旧的 tr 替换两个 trs (你只需要通过给新的 trs 一个你可以在 jquery 中轻松找到的属性来挂钩它)

  4. 不要忘记关闭全局键以防止重复编辑,用户可以一次编辑一行


更新:添加第二个解决方案以在客户端而不是服务器上转储负载

为了避免服务器超载(尽管在它成为一种常规习惯之前我不会担心它),您可以将表单字段作为 HTML 中的模板并使用字符串替换(或 jQuery 模板),而不是 ajaxing在第 2 步中获得响应,调用模板,并将字符串替换为保存在每一行中的属性......就像这样:

<div id="myTemplate"> // or you can use jQuery script templates
    <tr><td><input type="text" name="${Name}" ... /> id is ${Id}</td><td>${SecondRow}... </td></tr>
    <tr><td colspan="2">Save button here.... and may be more text ${MoreText}</td></tr>  
</div>

在代码的每一行中添加足够的属性或 ID 以了解您想要替换的内容,如下所示:

<tr data-itemid="34"><td ><input type="text" name="text1" id="findme" ... /></td><td data-moretext="here is more text">second column </td></tr>...etc

所以现在在你的替换脚本中:

$("#myTemplate").html().replace("${Name}", $(thisrow).find("#findme").attr("name"))
    .replace("${Id}",$(thisrow).attr("data-itemid"));

ETC...

当然,提交后它必须是一个到服务器,但如果用户“取消”你可以有另一个只读模板

顺便说一句,这是我通常使用的方式,我使用 jQuery 模板,创建编辑和查看模板,但我也重复编辑表单,我手动使用 jQuery ajax 提交......但是......我的朋友,是恐怕不是一个简单的清洁和可维护的解决方案

于 2012-10-09T12:59:21.877 回答
1

怎么样contenteditable

演示:http: //jsfiddle.net/SO_AMK/XQekC/

jQuery:

var ctrlDown = false;
$(document).keydown(function(e) {
    if (e.which = "ctrlKey") {
        ctrlDown = true;
    }
}).keyup(function(e) {
    if (e.which = "ctrlKey") {
        ctrlDown = false;
    }
});


$('#example').dataTable();

$("#example tr").click(function() {
    if ($(this).hasClass("row_selected") && ctrlDown) {
        submitRow($(this));
        return false; // Break out so the next if doesn't run
    }
    else if ($(this).hasClass("row_selected") && ctrlDown == false) {
        return false; // Break out so the next if doesn't run
    }

    if ($(this).siblings(".row_selected").length && ctrlDown == false) {
        $(this).siblings(".row_selected").each(function() {
            submitRow($(this));
        });
    }

    $(this).addClass("row_selected");
    $(this).children("td").each(function() {
        $(this).attr("contenteditable", true);
    });
});

function submitRow(elm) {
    var data = [];
    $(elm).removeClass("row_selected").children("td").each(function() {
        data.push($(this).text());
    });
    alert(data); // This will stop the keyup from firing, but you won't (I hope) really be using alerts
}​

除了提交到服务器功能外,它具有所有功能,它也是完全内联的,并且支持选择多行。

唯一的错误是,当它显示数据警报时,焦点会离开主窗口,因此 keyup 事件永远不会触发,因为您可能不会使用警报,这应该不是问题。要在小提琴中修复它,请在警报关闭后按下并释放 ctrl,然后再单击一行。

于 2012-10-12T15:49:18.233 回答
1

There is another solution, but I'm under the impression you won't like it very much... you can use a single form for the whole datatable (wrapping the whole table in a form is permitted) generate input fields for the current row and if it's updated submit the form asyncronously with javascript and restore td contents to the original html, if you name your fields such as name="field[]" you can also submit multiple rows at a time (I don't know if you'd want that though).

You can write html code such as

<form action="">
<table>
<tr><td><input type="hidden" name="row[]" value="1"/><input name="field[]"/></td></tr>
<tr><td>field value for row2</td></tr>
<tr><td><input type="hidden" name="row[]" value="3"/><input name="field[]"/></td></tr>
</table>
</form>

you can just grab the form with jquery and submit it via xmlhttprequest as I suspect you would if each row was a separate form (which is illegal), if you don't want multiple rows, just remove the [] and submit each row and upon submitting the values you get them numbered correctly, don't know exactly how it would behave in java but in php I'd get the following:

$_GET[row][0] = 1;
$_GET[field][0] = 'value typed in row1';
$_GET[row][1] = 3;
$_GET[field][1] = 'value typed in row3';

Alternative table definition to avoid having the same name again

<form action="">
<table>
<tr><td><input name="field[1]"/></td></tr>
<tr><td>field value for row2</td></tr>
<tr><td><input name="field[3]"/></td></tr>
</table>
</form>

It's the same table as above only you set explicit indexes for each entry thus avoiding duplicate names in the response, preferrably use a unique identifier which can describe the row from the table that you're modifying in there (when possible I use the primary key) instead of the row number, just in case that wasn't clear enough.

于 2012-10-07T17:52:43.833 回答
1

一年前我就遇到过这样的问题。这是一个混乱的问题。无论哪种方式,如果您遍历行的每个 td 并将其转换为文本字段,或者您可以为此创建一个单独的 jsp 文件。

但是在这种情况下最好的是将 td 的内容更改为输入字段并手动发布数据。因为在这种情况下,您不能将表单标签包裹在 tr 周围。您必须手动发布每个输入字段的值。

PS 最好的解决方案是创建一个编辑对话框。

于 2012-10-05T05:02:19.020 回答
1

你有没有尝试过:

  1. 将整个表格包裹在表格中
  2. 将数据条目作为禁用输入,通过 CSS 隐藏其边框
  3. 当用户单击编辑时,启用输入并显示边框
  4. 您可能需要每个字段的隐藏元素
  5. 当用户提交表单时,通过 ajax 发布并将输入设置回禁用并隐藏边框
于 2012-10-09T11:52:08.563 回答
0

我看到几个问题

  1. 你没有。表格中的列与您显示的编辑列不同
  2. 您可能没有完整的数据来编辑该行,因此您可能需要进行 Ajax 调用并获取它

如果您有完整的数据,那么您不需要第 2 点,假设您有一个函数 f 以单击的 tr 作为参数调用

function f(row)
{
     var newRow = yourTable.insertRow(parseInt(row.rowIndex,10)+1);
     //you can place the above or below the clicked row , or you can even make the row visible false And then show the new row
     Var newCell = newRow.insertCell(0);
     newCell.colspan = 6;//the count if columns in your table row
     NewCell.innerHTML = " put your HTML content here";
}
于 2012-10-13T04:38:58.753 回答