如何在表格中对齐表单字段以进行内联编辑?

时间:2012-10-05 03:18:22

标签: javascript jquery html css spring

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

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

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

  1. 我可以获取所选行的句柄,然后迭代td并将它们转换为输入/选择字段。然后,我可以为新字段和保存按钮插入一个额外的行。 我不认为这是一个干净的解决方案。我将不得不手动发布Post而不是使用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>

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

    生成的html看起来像                                           ...     

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

    Image showing the bad alignment

    您可以建议更好的解决方案吗? 如果问题不是很清楚,我可以填写更多细节。

6 个答案:

答案 0 :(得分:3)

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

  1. 用单一表格包裹表格
  2. on编辑行(点击行)打开一个ajax请求,返回看起来像精确tr的纯html,只包含你要包含的额外内容:

  3. <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. 不要忘记关闭全局密钥以防止双重编辑,用户可以一次编辑一行


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

      为了避免服务器过载(虽然我不会担心它会成为常规习惯),你可以将表单字段作为HTML中的模板并使用字符串替换(或jQuery模板),在步骤2中获取响应的ajaxing,你调用模板,并用你在每一行保存的属性替换字符串......像这样:

      <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"));
      

      等...

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

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

答案 1 :(得分:1)

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

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

P.S最佳解决方案是创建编辑对话框。

答案 2 :(得分:1)

还有另一个解决方案,但我的印象是你不会非常喜欢它...你可以使用单个表单来表示整个数据表(允许以表格形式包装整个表)生成输入字段对于当前行,如果已更新,则使用javascript同步提交表单并将td内容恢复为原始html,如果您将字段命名为name =“field []”,则还可以一次提交多行(我不是知道你是否想要那个。)

您可以编写HTML代码,例如

<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>

您可以使用jquery抓取表单并通过xmlhttprequest提交它,因为我怀疑如果每行都是一个单独的表单(这是非法的),如果您不想要多行,只需删除[]并提交每一行 并且在提交值得到它们正确编号后,不知道它在java中的确切行为,但在php中我会得到以下内容:

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

替代表定义,以避免再次使用相同的名称

<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>

与上面相同的表只是为每个条目设置显式索引,从而避免响应中的重复名称,最好使用唯一标识符,该标识符可以描述您在那里修改的表中的行(如果可能,我使用主键)而不是行号,以防万一不够清楚。

答案 3 :(得分:1)

你试过了吗?

  1. 以表格
  2. 包裹整个表格
  3. 将数据条目作为禁用输入,并通过CSS隐藏其边框
  4. 当用户点击编辑时,启用输入并显示边框
  5. 您可能需要为每个字段隐藏元素
  6. 当用户提交表单时,通过ajax发布并使用隐藏边框将输入设置为已禁用

答案 4 :(得分: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,然后再单击一行。

答案 5 :(得分:0)

我看到了几个问题

  1. 你的不。表中的列和&amp;您显示的编辑列是不同的
  2. 您可能没有完整的数据来编辑行,因此您可能需要执行Ajax调用并获取它
  3. 如果您有完整的数据,则不需要第2点,假设您使用单击的tr作为参数调用函数f

    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";
    }