我有一个table_id =“mytable”的表
我需要在点击提交后发送动作子程序中表格的所有行。在子例程中,我需要在修改一些值后逐个将行插入到表中。
最简单的方法是什么?
我的真实模板:
<form method="post" action="/savesmop" >
<section class="wrapper">
<h1>Select Items and add components</h1>
<ul class="tabs">
<% FOREACH Component_Id IN components.keys.nsort %>
<li><a href="#tab<% components.$Component_Id.Component_Id %>"><% components.$Component_Id.Component_Name %></a></li>
<% END %>
</ul>
<div class="clr"></div>
<section class="block">
<% FOREACH Component_Id IN **components.keys.nsort** %>
<article id="tab<% components.$Component_Id.Component_Id %>">
<% FOREACH ACTIVITY_ID IN activities.keys.nsort %>
<% IF activities.$ACTIVITY_ID.Component_Id == components.$Component_Id.Component_Id %>
<input class="toggle-box" id="t<% activities.$ACTIVITY_ID.ACTIVITY_ID %>" name="t<% activities.$ACTIVITY_ID.ACTIVITY_ID %>" type="checkbox" >
<label for="t<% activities.$ACTIVITY_ID.ACTIVITY_ID %>"><% activities.$ACTIVITY_ID.ACTIVITY_NAME %>
<input type="button" class="btnsmall1" onclick="addRow('<% activities.$ACTIVITY_ID.ACTIVITY_ID %>')" value="+" />
<input type="button" class="btnsmall2" onclick="deleteRow('<% activities.$ACTIVITY_ID.ACTIVITY_ID %>')" value="X" />
</label>
<div>
<table id="<% activities.$ACTIVITY_ID.ACTIVITY_ID %>" name="<% activities.$ACTIVITY_ID.ACTIVITY_ID %>">
<tr><td><input type="checkbox" name="chk"/></td>
<% FOREACH ATTRIBUTE_ID IN attributes.keys.nsort %>
<% IF attributes.$ATTRIBUTE_ID.ACTIVITY_ID == activities.$ACTIVITY_ID.ACTIVITY_ID %>
<td>
<% IF attributes.$ATTRIBUTE_ID.ATTRIBUTE_NAME == 'Object Type' %>
<select id="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_ID %>" name="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_ID %>">
<option value="" disabled selected>Select Object Type</option>
<option value="TABLE">TABLE</option>
<option value="VIEW">VIEW</option>
<option value="OTHER">OTHER</option>
</select>
<% ELSIF attributes.$ATTRIBUTE_ID.ATTRIBUTE_NAME == 'SVN Path' %>
<input size="90" type="TEXT" placeholder="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_NAME %>" id="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_ID %>" name="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_ID %>"/>
<% ELSE %>
<input type="TEXT" placeholder="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_NAME %>" id="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_ID %>" name="<% attributes.$ATTRIBUTE_ID.ATTRIBUTE_ID %>"/>
<% END %>
</td>
<% END %>
<% END %>
</tr>
</table>
</div>
<br>
<% END %>
<% END %>
</article>
<% END %>
</section>
</section>
<input class="btn2" type="submit" value="SAVE" />
</form>
我从3个不同的数据库表中选择了3个哈希值,并循环遍历它们以动态生成此模板。
正如您所看到的,每个列表项中都有多个表,每个表中的列数也不同。我在javascript中做的是在添加一行时克隆表的第一行。在javascript addrow函数中添加新行时,我无法弄清楚如何将每个文本输入的名称标记增加1。
以下是我的javascript函数:
function deleteRow(tableID)
{
try
{
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
for(var i=0; i<rowCount; i++)
{
var row = table.rows[i];
var chkbox = row.cells[0].childNodes[0];
if(null != chkbox && true == chkbox.checked)
{
table.deleteRow(i);
rowCount--;
i--;
}
}
}
catch(e){alert(e);}
}
function addRow(tableID)
{
var table = document.getElementById(tableID); // find table to append to
var row = document.getElementById(tableID).rows.item(0); // find row to copy
var clone = row.cloneNode(true); // copy children too
clone.id = "newID"; // change id or other attributes/contents
table.appendChild(clone); // add new row to end of table
}
答案 0 :(得分:1)
由于您没有说明您使用的是哪个舞者版本,我将假设您使用的是first version of Dancer(而不是Dancer2)。
看起来您不确定表单在通过GET或POST提交时的工作方式。这不是特定于Dancer,而是非常通用于HTTP协议如何工作,并且与HTML相关联。
如果HTML文档中有表单,则<input>
和<textarea>
等表单元素需要具有name
属性。这就是请求的内容。 id
属性仅适用于CSS和JS(这是简化的)。
<form action="/save" method="GET">
<input type="text" name="foo" id="input-foo" />
<input type="submit" value="save" />
</form>
如果您输入 bar 并点击该按钮,您的浏览器将导航至:
/save?foo=bar
如果name
上没有<input>
属性,浏览器将忽略该属性。
<form action="/save" method="GET">
<input type="text" id="input-foo" />
<input type="submit" value="save" />
</form>
这将引导您:
/save
如果您不希望显示value
按钮的submit
,这也很有用。只是不要给它name
属性。
好的,现在您有多行输入字段。那些是动态的。您为id
和<table>
元素分配了整数作为<input>
s。这很奇怪,但不应该是一个问题。但没有name
属性。
您应该为每个<input>
指定一个不同的名称。例如,使用与占位符相关的名称。
<table id="101">
<tr>
<td><input type="checkbox" name="chk" /></td>
<td><input type="text" placeholder="Database Name" name="dbname-1" /></td>
<td><input type="text" placeholder="Database Appx Size" id="appx-1" /></td>
<td><input type="text" placeholder="Rate of growth" id="growth-1" /></td>
</tr>
</table>
现在有一行有三个不同的名称:dbname-1
,appx-1
和growth-1
。
让我们看看JavaScript添加新行。我不会在这里展示它,但它应该做的是包括name
属性和增量数字。下一行应包含以下名称:dbname-2
,appx-2
和growth-2
。你在这里得到了模式。
最后,我们需要在Perl代码中做一些事情。我们将获得所有参数,将它们过滤到我们感兴趣的三种字段类型,然后迭代它们以插入它们。我们还要确保它们不是空的。
post '/savesmop' => sub {
# get all the parameters
my %values = params;
# remove unwanted ones that don't belong to the rows
foreach my $key ( keys %values ) {
delete $values{$key} unless $key =~ m/^(?:dbname|appx|growth)-/;
}
my $dbh = DBI->connect( 'dbid', 'user', 'pwd' ) or die $DBI::errstr;
my $sth = $dbh->prepare("INSERT INTO TABLE_Fact VALUES (?,?,?)") or die $dbh->errstr;
# iterate over the dbnames only
foreach my $dbname ( grep {m/^dbname/} sort keys %values ) {
# field should not be empty
next unless $values{$dbname};
# fetch the number from the dbname...
( undef, my $id ) = split /-/, $dbname;
# ... and the other two should exist and not be empty also
next unless my $appx = $values{ 'appx-' . $id };
next unless my $pwd = $values{ 'pwd-' . $id };
# now insert
$sth->execute( @values{ $dbname, $appx, $pwd } ) or die $dbh->errstr;
}
template "savesmop";
};
关于这一点的一点是,你不需要知道有多少。 while
循环不是将内容插入数据库的最佳方法。通常,您使用for
循环迭代数据。 Perl的foreach my $item (@list)
语法特别有用,因为您不必关心数组/列表的长度。
一些侧节点:
$dbh
,你不需要关心连接。如果你根本不想要插件(这不是一个明智的决定,如果其他人完成了这项工作并且经过了充分的测试,它总是很好!),至少不要重新制作连接到路由处理程序中的数据库。 Dancer持续运行(除非您将其作为CGI运行),因此它将从保持连接打开中受益。连接到应用程序代码顶部的数据库,并将其保存在config
中。这很奇怪,但效率更高。
use Dancer;
use DBI;
config 'dbh' => DBI->connect('...') or die $DBH::errstr;
get '/foo' => sub {
config->dbh->prepare('select ...');
}