如何从模板到子程序获取表值?

时间:2015-08-25 17:59:16

标签: perl dancer

我有一个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
       }

1 个答案:

答案 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-1appx-1growth-1

让我们看看JavaScript添加新行。我不会在这里展示它,但它应该做的是包括name属性和增量数字。下一行应包含以下名称:dbname-2appx-2growth-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)语法特别有用,因为您不必关心数组/列表的长度。

一些侧节点:

  • 您是否考虑过使用DBIx::Class?有一个很好的插件称为Dancer::Plugin::DBIC,可以很容易地在您的Dancer应用程序中使用。 DBIx :: Class有一些学习曲线,但值得!
  • 如果您被对象关系映射器吓倒或认为它太过分,请查看Dancer::Plugin::Database。它有助于抽象出$dbh,你不需要关心连接。
  • 如果你根本不想要插件(这不是一个明智的决定,如果其他人完成了这项工作并且经过了充分的测试,它总是很好!),至少不要重新制作连接到路由处理程序中的数据库。 Dancer持续运行(除非您将其作为CGI运行),因此它将从保持连接打开中受益。连接到应用程序代码顶部的数据库,并将其保存在config中。这很奇怪,但效率更高。

    use Dancer;
    use DBI;
    
    config 'dbh' => DBI->connect('...') or die $DBH::errstr;
    
    get '/foo' => sub {
      config->dbh->prepare('select ...');
    }