我有一个网络应用程序,主要由一个包含信息的大表单组成。该表单分为多个选项卡,以使其对用户更具可读性:
<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 中不允许嵌套表单。但是,我确实需要在该选项卡上显示表单:它是该页面功能的一部分。我还想要单独表单的行为:当用户在表单字段中点击回车键时,按下“添加”提交按钮,并在部分表单上触发提交操作。
解决这个问题的最佳方法是什么?
I've got a web application, consisting mainly of a big form with information. The form is split into multiple tabs, to make it more readable for the user:
<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>
The form is dynamically extended (extra rows are added to the tables).
Every 10 seconds the form is serialized and synchronized with the server.
I now want to add an interactive form on one of the tabs: when a user enters a name in a field, this information is sent to the server and an id associated with that name is returned. This id is used as an identifier for some dynamically added form fields.
A quick sketchup of such a page would look like this:
<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>
The above will not work: nested forms are not allowed in HTML. However, I really need to display the form on that tab: it's part of the functionality of that page. I also want the behaviour of a separate form: when the user hits return in the form field, the "Add" submit button is pressed and a submit action is triggered on the partial form.
What is the best way to solve this problem?
发布评论
评论(9)
您可以做的一件事是将“Add”输入元素的类型设置为“submit”,而是将其设置为“button”并添加用于注册点击处理程序的
id
属性:原因对于输入类型“按钮”,页面上生成的按钮看起来与提交按钮完全相同,但默认情况下单击时不执行任何操作,允许您自定义其效果。此外,所有支持 HTML 3.2 或更高版本的浏览器都支持输入类型“button”包括 HTML 5。
在 Javascript 中的某个位置,您可能有一个希望在用户单击“添加”按钮时调用的函数。假设它被称为
addAnotherPerson
,您只需在点击处理程序中调用addAnotherPerson
:您还需要向“额外”文本输入添加一个 keydown 处理程序以执行相同的操作当用户按下 Enter 键时:
请务必将属性
autocomplete="off"
添加到“额外”文本输入。addAnotherPerson
函数可以发送一个异步 POST 请求,其中包含“extra”文本框中的值,然后在适当的情况下更新 DOM。编辑:如果您还想支持禁用 Javascript 的用户,则可以向每个提交按钮添加具有唯一
name
属性值的name
属性对于每个按钮,您的服务器端应用程序将能够知道用户单击了哪个按钮。例如,以下代码来自 http://www.alanflavell.org.uk/www /trysub.html:
如果用户单击“啤酒”旁边的“[O]”按钮,则浏览器会发送“啤酒”POST 变量,而不是“aquavit”、“香槟”或“水”POST 变量。尝试一下 http://www.alanflavell.org.uk/www/trysub.html 。
此技术的一个棘手问题是用户通过在文本输入中按 Enter 键来提交表单的情况。 Firefox 为表单中的第一个提交按钮(本例中为“aquavit”)发送 POST 变量,而 Internet Explorer 不会为任何提交按钮发送 POST 变量。您可以通过在表单的最开头添加一个隐藏的无名提交按钮来修补此差异:
EDIT2: 如果您始终确保“额外”文本输入中的值被 Javascript 清除在提交大表单之前,您将能够判断用户是否禁用了 Javascript,并且他们在“额外”文本输入中按 Enter 键(表明他们想要添加-通过检查“额外”POST 变量在服务器端是否不为空来运行)。如果它不为空,那么您可以假设用户禁用了 Javascript 并且他们想要添加一个人。
添加此代码:
One thing that you could do is instead of setting the type of the "Add" input element to "submit", set it to "button" and add an
id
attribute for registering a click handler:The reason for input type "button" is that the resulting button on the page looks exactly like a submit button, but it does nothing by default when clicked, allowing you to customize its effect. Also, input type "button" is supported in all browsers that support HTML 3.2 or later including HTML 5.
Somewhere in your Javascript you probably have a function that you wish to be called whenever the user clicks the "Add" button. Supposing that it is called
addAnotherPerson
, you simply calladdAnotherPerson
within a click handler:You also need to add a keydown handler to the "extra" text input to perform the same action when the user presses down the Enter key:
Be sure to add the attribute
autocomplete="off"
to the "extra" text input.The
addAnotherPerson
function could send an asynchronous POST request containing the value in the "extra" text box, updating the DOM afterward if appropriate.EDIT: If you also want to support users who have Javascript disabled, then by adding
name
attributes to every submit button with a uniquename
attribute value for each, your server-side application will be able to tell which button that the user clicked.Take, for example, this code from http://www.alanflavell.org.uk/www/trysub.html:
If the user clicks on the "[O]" button next to "Beer", then the browser sends a "beer" POST variable, but not an "aquavit", "champagne", or "water" POST variable. Try it out at http://www.alanflavell.org.uk/www/trysub.html.
One tricky issue with this technique is the case where the user submits the form by pressing the Enter key within a text input. Firefox sends a POST variable for the first submit button in the form ("aquavit" in this case) whereas Internet Explorer does not send a POST variable for any of the submit buttons. You can patch over this difference by adding a hidden, nameless submit button to the very start of the form:
EDIT2: If you always make sure that the value in the "extra" text input is cleared by Javascript before the big form is submitted, then you will be able to tell if the user has Javascript disabled and they press the Enter key in the "extra" text input (indicating that they want the add-a-person action to run) by checking whether the "extra" POST variable is not empty on the server side. If it is not empty, then you can assume that the user has Javascript disabled and that they want to add a person.
Add this code:
HTML 应该是语义化的,并且应该首先考虑它 - 即它应该具有清晰的结构和含义,而无需了解 javascript 位于之上。就像
应仅包含
元素一样,
重要的是您仍然可以在主窗体中实现所需的流程。在主窗体上,不要使用嵌套窗体,而是使用
现在通过 Javascript 不显眼地添加所需的行为,方法是:
#newperson
。event.which
而不是event.keyCode
,因为 jQuery 对此进行了规范化。您需要event.which == 13
作为回车键。$("#newperson").submit()
之前,将代理输入中的值复制到真实表单。这有效地将序列化和发送数据的责任委托给第二种形式,允许将任何类型的逻辑附加到第二种形式,并与第一种形式解耦。
此外,由于首先考虑的是功能性 HTML,一个简单的调整就可以让表单在没有 Javascript 的情况下完美工作 - 只需使用 CSS 隐藏
HTML should be semantic, and it should be considered first - i.e. it should have a clear structure and meaning without an understanding of what javascript lies on top. Like the way a
<ul>
should only contain<li>
elements, a<form>
should have only a single purpose. Using javascript to enhance a form by retrieving dynamic data is fine, but if an extra HTTP POST is used (the type that modifies data on the server), then this really represents a second purpose, and thus a second form should be used. A second form, with its own "action" attribute, signals that a distinct behaviour is happening here, and is not only more conceptually sound, but easier to analyse, debug or extend when necessary.The important thing is that you can still achieve the desired flow within the main form. On your main form, instead of using a nested form, use a
<fieldset>
. This fieldset will behave as a proxy for the newperson form. The input inside here can have an ID, but should not have a name since its value is not meant to be submitted with the main form. As already mentioned in other answers, the button should be changed to a type of "button" and not "submit".Now add the desired behaviour unobtrusively through Javascript, by:
#newperson
.#newpersonProxy
, as well as to the click event of the button. For the keyup event, useevent.which
instead ofevent.keyCode
as jQuery normalises this. You wantevent.which == 13
for the enter key.$("#newperson").submit()
.This is effectively delegating the responsibility of serializing and sending the data to the second form, allowing any sort of logic to be attached to the second form, and be de-coupled from the first.
Further, as functioning HTML was considered first, a simple tweak can allow the forms to work perfectly without Javascript - just hide the
<fieldset>
using CSS, and show it with Javascript. If Javascript is turned off, the tabs will break apart, the nested fieldset will be hidden, and the second form will be displayed (and fully functioning, just not via AJAX).像下面这样的事情应该可以做到。
如果 JavaScript 被禁用,您将需要检测用户是否按下了“Add”
submitButton
:Something like the following should do it.
If JavaScript is disabled you will need to detect if the user pressed the "Add"
submitButton
with:这并不像其他答案那么冗长,但是..
它应该非常简单;)
不过,这里有一个示例,它显示了我所引用的格式的一点这保留了表单标签,是我使用 scriptaculous 库时的一个旧示例。这是 JS,它演示了一些结构。
如果您+1我并让我知道您喜欢这个答案,我将为您开发一个功能示例;)
干杯!
柯克
This isn't nearly as verbose as the other answers, but..
It should be super easy ;)
Here's an example that shows a bit of the formatting I'm referencing, however this retains the form tags and is an older example from when I used the scriptaculous library. Here's the JS, it demonstrates the a bit of the structuring.
If you +1 me and let me know u like this answer, I will develop a functional example for you ;)
Cheers!
Kirk
为什么不嵌套表单对象并在一个 php 代码中处理所有操作...
然后在后端使用 php 逻辑来创建关联(如果它是“新”的):
Why don't you nest the form objects and handle ALL the actions in one php code...
Then use php logic on the backend to create the association if it is "new":
您可以将添加表单移出父表单并使用 CSS 隐藏它,然后,正如另一位海报所说,用具有正确 id 的按钮替换添加表单的提交按钮,最后,挂钩到输入上的两个 onkeypress ,然后单击按钮来模拟实际添加表单的提交。
据我所知,这应该可以完成您需要的一切,同时保留原始功能。
注意:
#add_person_form
表单上实际上并不需要提交按钮,我只是将其保留在那里,以便您可以轻松查看我将表单“移动”到的位置。You could move the add form outside of the parent form and hide it using CSS, then, as another poster said, replace the submit button for the add form with a button with a correct id, and finally, hook into both onkeypress on the input, and onclick on the button to simulate a submission of the actual add form.
This should do everything you need while retaining the original functionality, as far as I can tell.
Note: The submit button isn't really needed on the
#add_person_form
form, I just kept it there so you can easily see where I 'moved' your form to.我看到处理类似场景的方式是为“内部”表单创建一个模式页面,因此不需要嵌套。我不认为这种方法会严重阻碍页面的流动。
否则,通过 AJAX 提交“内部”表单或整个表单的其他建议也可以起作用。
The way I've seen similar scenarios handled is to create a modal page for the "inner" form so no nesting is required. I do not see this method significantly hampering the flow of the page.
Otherwise the other suggestions to submit either the "inner" form or the entire form via AJAX can work as well.
您不需要嵌套表单,您可以使用另一个表单(非嵌套)并使用绝对定位将其放置在页面上的任何位置。无论如何,所有这些具有与用户输入的名称相关的 id 的动态控件的创建似乎非常复杂。如果您可以分享您可能试图解决的业务问题,也许我们可以有一个更简单的解决方案。
You don't need a nested form, you can use another form(not nested) and use absolute positioning to place it anywhere on the page..anyways all this creation of dynamic controls with id related to name entered by users seems very complicated..may be we can have a more simpler solution if you could share the business problem you may be trying to solve.
您可以使用 ajax 或在第一个表单之外创建其他表单,并使用绝对 DIV 层对其进行定位。
使用 javascript 可以轻松读取图层位置。首先,您将制作一个具有预定义高度的占位符,然后您可以在占位符上方显示表单。
您显示 .placeholder 所在的第二个表单
You can use ajax or make the other form outside of the first one and position it using absolute DIV layer.
It's easy to read layer position using javascript. First you will make a placeholder with pre-defined height, then you can display the form above placeholder.
You display the second form where .placeholder is