简体   繁体   中英

How to save more that one row of text to database by adding input fields dynamically?

What I have and doing at the moment:

When the webpage loads the user is presented with form fields to type in some information then the user has the option the add more fields and add more information.

Then once the user is done they can click on the save button and then it will save the information to my database.

This is the code I have at the moment:

aspx

<script type="text/javascript">
    function ExtractData() {
        var strValue = GetString();
        alert(strValue);
        if (strValue != "ERROR") {
            E("<%=hdnData.ClientID %>").value = strValue;
            return true;
        } else {
            return false;
        }
    }
    function GetString() {
        return "Item:" + E("item1").value + ";Quantity:" + E("qty1").value + ";Cost:" + E("cost1").value + ";Price:" + E("price1").value;
    }

    function E(id) {
        return document.getElementById(id);
    }

</script>
<style>
    table, th, td {
        border: 1px solid black;
        border-collapse: collapse;
    }
</style>
<script type="text/javascript">
    function sum() {
        var val1 = document.getElementById('TextBox4').value;
        var val2 = document.getElementById('TextBox5').value;
        var sum = Number(val1) + Number(val2);
        document.getElementById('TextBox6').value = sum;
    }
</script>

<div class="container-fluid">
   <table id="dataTable" width="350px" border="1" style="border-collapse: collapse;">
      <tr>
         <th>Select</th>
         <th>Item Number</th>
         <th>Description</th>
         <th>Qty</th>
         <th>Rate</th>
         <th formula="cost*qty" summary="sum">Price</th>
      </tr>
      <tr>
         <td>
           <input type="checkbox" name="chk[]" /></td>
         <td>1 </td>
         <td>
           <input type="text" id="item1" name="item[]" />
         </td>
         <td>
           <input type="text" id="qty1" name="qty[]" />
         </td>
         <td>
           <input type="text" id="cost1" name="cost[]" />
         </td>
         <td>
           <input type="text" id="price1" name="price[]" />
         </td>
         </tr>
         </table>
       <br />
       <input type="button" class="btn-warning" value="Add Row" onclick="addRow('dataTable')" />
       <input type="button" class="btn-danger" value="Delete Row" onclick="deleteRow('dataTable')" />
       <input type="button" class="btn-info" value="Total" onclick="totalIt()" />
       <asp:ImageButton ID="submitButton" runat="server" src="images/send.gif"
            OnClientClick="return ExtractData();" OnClick="saveQuote_Click" /><br />
       <asp:HiddenField ID="hdnData" Value="" runat="server" />
       <asp:Label ID="message" runat="server" />
 </div>

aspx.cs

string connStr = @"connection string to database";
protected void saveQuote_Click(object sender, EventArgs e)
{
    System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(connStr);
    try
    {
        conn.Open();
        System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(@"INSERT INTO tbl_newQuotes(Item,Description,Rate,Quantity,Price) values(@Item,@Description,@Rate,@Quantity,@Price)", conn);
        cmd.Parameters.AddWithValue("@Item", GetStr("Item"));
        cmd.Parameters.AddWithValue("@Description", GetStr("Item"));
        cmd.Parameters.AddWithValue("@Rate", GetStr("Quantity"));
        cmd.Parameters.AddWithValue("@Quantity", GetStr("Cost"));
        cmd.Parameters.AddWithValue("@Price", GetStr("Price"));
        cmd.ExecuteNonQuery();
    }
    catch (Exception ex)
    {

    }
    finally
    {
        conn.Close();
    }
}
private string GetStr(string title)
{
    string[] mystr = hdnData.Value.Split(";".ToCharArray());
    string value = string.Empty;
    foreach (string Str in mystr)
    {
        string[] namePair = Str.Split(":".ToCharArray());
        if (namePair[0] == title)
        {
            value = namePair[1];
            break;
        }
    }
    return value;
}

The Problem I am facing

So as you can see the above code reads the input values by using jscript and extracting it then saves to the database. All of this works well, but when the users adds more field the that data is not saved only the first field does.

I need to get it to save every row of input fields added to the database.

Any help will be appreciated. Thanks

To update grids or repeating data? You don't hard code this, you use one of MANY data aware and data repeating controls.

I like listview over grid view. I used the wizards to generate this, deleted all the templates and now have this markup:

<form id="form1" runat="server">
    <div>
        <link href="Content/cuscosky.css" rel="stylesheet" />
        <asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
            <EmptyDataTemplate>
                <table runat="server" style="">
                    <tr>
                        <td>No data was returned.</td>
                    </tr>
                </table>
            </EmptyDataTemplate>
            <ItemTemplate>
                <tr id="myTable1" style="">
                    <td><asp:Label ID="IDLabel1" runat="server" Text='<%# Eval("ID") %>' /></td>
                    <td><asp:TextBox ID="DescriptionTextBox" runat="server" Text='<%# Eval("Description") %>' /></td>
                    <td><asp:TextBox ID="tQty" runat="server" Text='<%# Eval("Qty") %>' style="width:40px"
                       onchange="updatecost(this.id,'tQty');"  />
                    </td>
                    <td>
                        <asp:TextBox ID="tUnitPrice" runat="server" Text='<%# Eval("UnitPrice") %>' style="width:70px;text-align:right"  
                            onchange="updatecost(this.id,'tUnitPrice');"/>
                    </td>

                    <td><asp:TextBox ID="tCost" runat="server" Text='<%# Eval("Qty") * Eval("UnitPrice") %>' style="width:70px;text-align:right"  /></td>
                </tr>

            </ItemTemplate>
            <LayoutTemplate>
                            <table id="itemPlaceholderContainer" runat="server" border="0" >
                                <tr runat="server" style="">
                                    <th runat="server">ID</th>
                                    <th runat="server">Description</th>
                                    <th runat="server">Qty</th>
                                    <th runat="server">UnitPrice</th>
                                    <th runat="server">Cost</th>
                                </tr>
                                <tr id="itemPlaceholder" runat="server">
                                </tr>
                            </table>
            </LayoutTemplate>
        </asp:ListView>
        <asp:TextBox ID="TextBox1" runat="server" ClientIDMode="Static"></asp:TextBox>
     <script>
         function updatecost(p, ctl) {

             var Qty = $('#' + p.replace(ctl, "tQty"));
             var UPric = $('#' + p.replace(ctl, "tUnitPrice"));
             var Cost = $('#' + p.replace(ctl, "tCost"));
             Cost.val(Qty.val() * UPric.val());
         }
     </script>

    </div>
</form>

As you can see, we don't have a lot of markup.

Now, to load up this grid in code? I have this code:

public class LvInvoiceEDit : System.Web.UI.Page
{
   private DataTable rstTable = new DataTable();

   protected void Page_Load(object sender, System.EventArgs e)
   {
       if (System.Web.UI.Page.IsPostBack == false)
       {
           LoadGrid();
           System.Web.UI.Page.Session["rstTable"] = rstTable;
       }
       else
           rstTable = System.Web.UI.Page.Session["rstTable"];
  }

   public void LoadGrid()
   {
       string strSQL = "";
       strSQL = "SELECT ID, Description, Qty, UnitPrice, Cost FROM InvoiceDetails";
       using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.Test3)))
       {
           cmdSQL.Connection.Open();
           rstTable.Load(cmdSQL.ExecuteReader);

           ListView1.DataSource = rstTable;
           ListView1.DataBind();
       }
   }
}

Not a lot of code so far, right? Well, we now have this grid:

在此处输入图像描述

Now I did play with some JavaScript to update the qty - I think I'll leave that for another day - but it does update quite nice.

So the NEXT big question then is HOW do I save the edit changes back to the data base?

Well, assuming we drop a save button below? Then this code will work:

protected void Button1_Click(object sender, EventArgs e)
{

// save all edits in the grid back to the table:

foreach (ListViewDataItem gvRow in ListView1.Items)
    {
       int ix = gvRow.DataItemIndex;
       {
           var withBlock = rstTable.Rows(gvRow.DataItemIndex);
           withBlock.Item("Description") = gvRow.FindControl("DescriptionTextBox") as TextBox.Text;
           withBlock.Item("Qty") = gvRow.FindControl("tQty") as TextBox.Text;
           withBlock.Item("UnitPrice") = gvRow.FindControl("tUnitPrice") as TextBox.Text;
           withBlock.Item("Cost") = gvRow.FindControl("tCost") as TextBox.Text;
       }
   }

// ok, grid is back to the table. Now send table back to database.

using (SqlCommand cmdSQL = new SqlCommand("SELECT ID, Description, Qty, UnitPrice, Cost FROM InvoiceDetails where id = 0", 
        new SqlConnection(My.Settings.Test3)))
{
    SqlDataAdapter da = new SqlDataAdapter(cmdSQL);
    SqlCommandBuilder cmdUpdate = new SqlCommandBuilder(da);

    da.Update(rstTable);
}
}

So a few things: See any mess or truckload of parameters in above? (no.)? Does it matter if we have 3 rows or 30 rows to update. (no!).

Did we really need to write any JavaScript? (no.).

So for bonus points, we probably in the save button should update the total box on the form.

Also, if you not doing a grid? Then I would tag your controls, write a loop to grab the controls into the table. And another routine to take a row and fill the controls. Once you write that routine? ( a fwriter, and rreader to pull or push one data row out to the controls?). Then you can use that fwriter/fread routine to update 5 or 50 controls on a form - and it will only take 2-3 lines of code to udpate those 3 or 40 controls on the form. So be it a grid (repeating rows), or that of just a bunch of controls on the form? You don't need to write and setup a gazillion things (don't need parameters - don't matter if 5 or 40 controls). And in the case of a table like layout (listview), it don't matter if we have 3 or 20 rows of data - its the SAME amount of code and work. This is how things were done on desktop - and the same applies to the web - you don't write code to inject repeating data (well, unless you say using PHP or some such). In asp.net land? We use data repeaters - and save world poverty in terms of the amount of code you do NOT have to write!

And like any desktop software for repeating data? you build the grid - fill it with data. You don't re-add controls on the form manually unless you looking to really make a huge amount of work when none is required.

So, the only trick/issue left? We need a add row button. I'll come back later today and post a few lines for that.

Edit: code to add a row? Drop a button below the grid, and thus the code is this to add a new row:

protected void Button2_Click(object sender, EventArgs e)
{

// add a new row to the table.

{
    var MyNewRow = rstTable.Rows.Add;
    MyNewRow.Item("Description") = "new row";
    MyNewRow.Item("Qty") = 1;
    MyNewRow.Item("UnitPrice") = 0;
    MyNewRow.Item("Cost") = 0;
}

// display this new row to the grid
ListView1.DataSource = rstTable;
ListView1.DataBind();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM