我有一个网络应用程序,主要由一个包含信息的大表单组成。表单分为多个选项卡,以使用户更具可读性:
<form>
<div id="tabs">
<ul>
<li><a href="#tab1">Tab1</a></li>
<li><a href="#tab2">Tab2</a></li>
</ul>
<div id="tab1">A big table with a lot of input rows</div>
<div id="tab2">A big table with a lot of input rows</div>
</div>
</form>
表单是动态扩展的(将额外的行添加到表中)。 每10秒钟,表单将被序列化并与服务器同步。
我现在想在其中一个标签上添加一个交互式表单:当用户在字段中输入名称时,会将此信息发送到服务器并返回与该名称相关联的ID。此ID用作某些动态添加的表单字段的标识符。
这样一个页面的快速草图将如下所示:
<form action="bigform.php">
<div id="tabs">
<ul>
<li><a href="#tab1">Tab1</a></li>
<li><a href="#tab2">Tab2</a></li>
</ul>
<div id="tab1">A big table with a lot of input rows</div>
<div id="tab2">
<div class="associatedinfo">
<p>Information for Joe</p>
<ul>
<li><input name="associated[26][]" /></li>
<li><input name="associated[26][]" /></li>
</ul>
</div>
<div class="associatedinfo">
<p>Information for Jill</p>
<ul>
<li><input name="associated[12][]" /></li>
<li><input name="associated[12][]" /></li>
</ul>
</div>
<div id="newperson">
<form action="newform.php">
<p>Add another person:</p>
<input name="extra" /><input type="submit" value="Add" />
</form>
</div>
</div>
</div>
</form>
以上操作无效:HTML中不允许使用嵌套表单。但是,我真的需要在该选项卡上显示该表单:它是该页面功能的一部分。我还想要一个单独表单的行为:当用户在表单字段中返回时,按下“添加”提交按钮并在部分表单上触发提交操作。
解决此问题的最佳方法是什么?
答案 0 :(得分:10)
您可以做的一件事是将“Add”输入元素的类型设置为“submit”,将其设置为“button”并添加id
属性以注册点击处理程序:
<!-- ... -->
<div id="newperson">
<p>Add another person:</p>
<input id="extra_input" name="extra" /><input id="add_button" type="button" value="Add" />
</div>
<!-- ... -->
输入类型“按钮”的原因是页面上的结果按钮看起来与提交按钮完全相同,但在单击时默认不执行任何操作,允许您自定义其效果。此外,支持HTML 3.2或更高版本including HTML 5的所有浏览器都支持输入类型“按钮”。
在您的Javascript中的某个地方,您可能希望在用户单击“添加”按钮时调用该函数。假设它被称为addAnotherPerson
,您只需在点击处理程序中调用addAnotherPerson
:
// This is jQuery code, but all JS frameworks that I have seen have a similar feature to register a click handler on a DOM element referenced by ID.
$("#add_button").click(function (event) {
addAnotherPerson();
$("#extra_input").val(""); // reset the value
});
您还需要在“额外”文本输入中添加一个keydown处理程序,以便在用户按下Enter键时执行相同的操作:
$("#extra_input").keydown(function (event) {
if (event.keyCode == 0xa || event.keyCode == 0xd) {
addAnotherPerson();
$("#extra_input").val(""); // reset the value
}
});
请务必将属性autocomplete="off"
添加到“额外”文字输入中。
addAnotherPerson
函数可以发送包含“额外”文本框中值的异步POST请求,如果合适,则在之后更新DOM。
编辑:如果您还想支持已禁用Javascript的用户,则可以向每个提交按钮添加name
个属性,每个提交按钮的属性值为name
个唯一值,您的服务器端应用程序将能够分辨用户单击的按钮。
例如,来自http://www.alanflavell.org.uk/www/trysub.html的代码:
<table>
<tr><td align=left><label for="aquavit_button"><input id="aquavit_button" type="submit" name="aquavit" value="[O]"> Aquavit</label></td></tr>
<tr><td align=left><label for="beer_button"><input id="beer_button" type="submit" name="beer" value="[O]"> Beer</label></td></tr>
<tr><td align=left><label for="champagne_button"><input id="champagne_button" type="submit" name="champagne" value="[O]"> Champagne</label></td></tr>
<tr><td align=left><label for="water_button"><input id="water_button" type="submit" name="water" value="[O]"> Dihydrogen monoxide</label></td></tr>
</table>
如果用户点击“Beer”旁边的“[O]”按钮,则浏览器会发送“啤酒”POST变量,但不会发送“aquavit”,“香槟”或“水”POST变量。在http://www.alanflavell.org.uk/www/trysub.html处尝试一下。
此技术的一个棘手问题是用户通过在文本输入中按Enter键提交表单。 Firefox为表单中的第一个提交按钮发送POST变量(在本例中为“aquavit”),而Internet Explorer不为任何提交按钮发送POST变量。您可以通过在表单的最开头添加隐藏的无名提交按钮来修补此差异:
<form action="bigform.php"><input type="submit" style="display:none;" />
<!-- ... -->
EDIT2:如果您始终确保在提交大表单之前通过Javascript清除“额外”文本输入中的值,那么您将能够判断用户是否具有Javascript 已禁用并通过检查“额外”POST变量是否为空而按下“额外”文本输入中的Enter键(表示他们希望添加一个人的操作)服务器端。如果它不为空,那么您可以假设用户已禁用Javascript并且他们想要添加一个人。
添加此代码:
$("#bigform").submit(function (event) {
$("#extra_input").val(""); // reset the value in the "extra" text input
return true;
});
答案 1 :(得分:6)
HTML应该是语义的,应该首先考虑 - 即它应该具有清晰的结构和意义,而不了解javascript位于顶部的内容。与<ul>
应该只包含<li>
元素的方式一样,<form>
应该只有一个目的。使用javascript通过检索动态数据来增强表单很好,但是如果使用额外的HTTP POST(修改服务器上的数据的类型),那么这实际上代表了第二个目的,因此应该使用第二种形式。第二种形式具有自己的“动作”属性,表示此处发生了不同的行为,并且不仅在概念上更合理,而且在必要时更容易分析,调试或扩展。
<form id="bigform" action="bigform.php">
<!-- Tabs here -->
</form>
<form id="newperson" action="newform.php">
<input name="extra">
<button type="submit" value="Add">
<!-- Note also the use of <button> instead of <input> -->
</form>
重要的是,您仍然可以在主窗体中获得所需的流量。在主窗体上,使用<fieldset>
而不是使用嵌套窗体。此字段集将充当newperson表单的代理。这里的输入可以有一个ID,但不应该有一个名称,因为它的值不应该与主表单一起提交。正如其他答案中已经提到的,按钮应该更改为“按钮”类型而不是“提交”。
<form id="bigform" action="bigform.php">
<!-- Tabs here -->
<fieldset id="newpersonProxy">
<input id="extra">
<button type="button" value="Add">
</fieldset>
</form>
现在通过Javascript 不加干扰地添加所需的行为:
#newperson
。#newpersonProxy
内任何输入的keyup事件以及按钮的click事件来响应“提交”。对于keyup事件,使用event.which
而不是event.keyCode
,因为jQuery会对此进行规范化。您希望输入密钥为event.which == 13
。$("#newperson").submit()
之前将值从代理输入复制到真实表单。这有效地将序列化和发送数据的责任委托给第二种形式,允许将任何类型的逻辑附加到第二种形式,并从第一种形式解除耦合。
此外,由于首先考虑正常运行的HTML,一个简单的调整可以让表单在没有Javascript的情况下完美地工作 - 只需使用CSS隐藏<fieldset>
,并使用Javascript显示它。如果Javascript被关闭,标签将分开,嵌套的字段集将被隐藏,第二个表格将被显示(并且完全正常运行,而不是通过AJAX)。
答案 2 :(得分:2)
以下内容应该这样做。
如果禁用JavaScript,则需要检测用户是否按下了“添加”submitButton
:
$_POST["submitButton"] == "Add"
<!-- other stuff goes here -->
<div id="newperson">
<p>Add another person:</p>
<input name="extra" id="extra" /><input name="submitButton" id="addPerson" type="submit" value="Add" />
</div>
</div>
</div>
</form>
<script>
var extra = $("#extra"),
addPerson = $("#addPerson").click(function(e){
// val would be the new person's name, e.g., "David"
var val = extra.val();
// you will want to give the user some AJAXy feedback here.
$.post(this.form.action, {"extra": val}, function(response){
// rest the extra div.
extra.val("");
/* 'response' could look like: */
// <div class="associatedinfo">
// <p>Information for David</p>
// <ul>
// <li><input name="associated[13][]" /></li>
// <li><input name="associated[13][]" /></li>
// </ul>
// </div>
$(response).insertBefore("#newperson");
// or 'response' could be json data, or whatever. I have a feeling
// you know enough about jQuery to handle the response-data. :-)
});
// prevent it from bubbling up.
e.preventDefault();
});
extra.keydown(function(e){
// submit the new person's name via ajax if enter is pressed.
if(e.keyCode === 13){
addPerson.click();
e.preventDefault();
}
});
</script>
答案 3 :(得分:2)
这并不像其他答案那么冗长,但是......
应该非常容易;)
这是一个example,它显示了我正在引用的格式 ,但是它保留了表单标记,是我使用scriptaculous库时的一个较旧的示例。这是the JS,它演示了一些结构。
如果你给我+1,让我知道你喜欢这个答案,我会为你开发一个功能性的例子;)
干杯! 柯克
答案 4 :(得分:1)
为什么不嵌套表单对象并在一个php代码中处理所有操作...
# have this form appended to the DOM via ajax/js when a link is clicked
<div id="newperson">
<p>Add another person:</p>
<input type="text" name="associated[new][]" />
</div>
然后在后端使用php逻辑创建关联,如果它是“new”:
foreach($_POST['associated'] as $obj) {
if($obj == "new")
// create a new record
else
// do your other processing
}
答案 5 :(得分:1)
你可以在父表单之外移动添加表单并使用CSS隐藏它,然后,正如另一张海报所说,用一个具有正确id的按钮替换添加表单的提交按钮,最后,挂钩到两个onkeypress在输入上,单击按钮以模拟实际添加表单的提交。
<form action="bigform.php">
....
<div id="newperson">
<p>Add another person:</p>
<input name="extra" /><button value="Add"/>
</div>
</div>
</div>
</form>
<div style='display:none;'>
<form action="newform.php" id='add_person_form'>
<input id='add_person_name' />
<input type="submit" id='add_person_submit' />
</form>
</div>
<script>
$('#newperson input').keyup(function(e) {
if(e.keyCode == 13) submitNewPersonForm();
});
$('#newperson button').click(function(e) {
submitNewPersonForm();
});
function submitNewPersonForm() {
// copy the content from the placeholder form
$('#add_person_name').val($("#newperson input").val());
// submit this form
$("#add_person_form").submit();
}
</script>
据我所知,这应该保留原始功能所需的一切。
注意:#add_person_form
表单上并不真正需要提交按钮,我只是将其保留在那里,以便您可以轻松查看我将表单移动到的位置。
答案 6 :(得分:1)
我看到处理类似场景的方式是为“内部”表单创建一个模态页面,因此不需要嵌套。我没有看到这种方法严重阻碍了页面的流动。
否则通过AJAX提交“内部”表单或整个表单的其他建议也可以。
答案 7 :(得分:1)
您不需要嵌套表单,可以使用其他表单(非嵌套)并使用绝对定位将其放置在页面的任何位置。所有这些创建的动态控件的id与用户输入的名称相关似乎非常复杂......如果你能分享你可能想要解决的业务问题,我们可以有一个更简单的解决方案。
答案 8 :(得分:0)
您可以使用ajax或使其他形式在第一个之外,并使用绝对DIV图层定位。
使用javascript轻松读取图层位置。首先,您将创建一个具有预定义高度的占位符,然后您可以在占位符上方显示该表单。
<form>
...
<div style='height: 300px;' class='placeholder'> ... </div>
</form>
<form>...<form>
显示.placeholder
的第二个表单