views:

314

answers:

2

When the user click's the add box attribute the row(i.e the row with 2 dropdown and textbox needs to be added) row with above needs to be dynamically created using jquery(so that there is no post back). User will be allowed to add as many attirbutes as he wants and when they click the check box that row needs to be deleted. How this can be achieved by jquery.

 <asp:Panel ID="pnl_BoxAttr" runat="server">
          <table>
             <tr>
                 <th>
                      Name
                  </th>
                  <th>
                      Comparision
                  </th>
                  <th>
                      Value
                  </th>
                  <th>
                      Delete
                  </th>
              </tr>
               <tr>
                   <td>
                       <asp:DropDownList ID="ddl_BoxName" runat="server">
                               <asp:ListItem Value="attr1" Selected="True"></asp:ListItem>
                               <asp:ListItem Value="attr2"></asp:ListItem>
                               <asp:ListItem Value="attr3"></asp:ListItem>
                       </asp:DropDownList>
                  </td>
                  <td>
                      <asp:DropDownList ID="ddl_BoxComparision" runat="server">
                             <asp:ListItem Value="=" Selected="true"></asp:ListItem>
                             <asp:ListItem Value=">"></asp:ListItem>
                             <asp:ListItem Value="<"></asp:ListItem>
                             <asp:ListItem Value="Like"></asp:ListItem>
                             <asp:ListItem Value="!="></asp:ListItem>
                             </asp:DropDownList>
                   </td>
                  <td>
                               <asp:TextBox ID="btn_boxval" runat="server" ></asp:TextBox>

                   </td>
                   <td>
                         <asp:CheckBox ID="chk_DeleteBoxRow" runat="server" />
                   </td>
             </tr>
             <tr>
                 <td colspan="3"> 
                     <asp:Button ID="btn_AddAttr" Text="Add Box Attribute" runat="server"/>
                 </td>
             </tr>
        </table>
        </asp:Panel>
A: 

As I understand it, you need the user to insert a new row (just like the one containing the select) by clicking a button?

First you need to give the tr with the add button an id, let's say 'addTr'.

For inserting, you could do something like this:

$('#btn_AddAttr').bind(
    'click',
    function() {
        $('#addTr').before( '<tr>' + 
                                /* entre tr content here */
                            '</tr>'
                          );
    }
);

Just be sure that all the dropdowns and textboxes have different ID's.

For removing the row from the table, you should add a class that would help you identify all the delete checkboxes, let's say 'delChk':

$('.delChk').bind(
    'click',
    function() {
        $(this).closest('<tr>').remove();
    }
);
A. M.
+4  A: 

To start with, here is a working demo, which you can reference throughout my answer: http://jsfiddle.net/EuyB8/.

Obviously the demo is in plain HTML rather than ASP.NET, but I will try to address the differences.

To start, since you will want to create some of the controls that you'll be cloning using .NET controls, my typical approach is to create a hidden template, which can then be used to create new copies. As such, I would have a row like the following:

<tr id="TemplateRow">
    <td>
        <asp:DropDownList ID="ddl_BoxName" runat="server">
            <asp:ListItem Value="attr1" Selected="True"></asp:ListItem>
            <asp:ListItem Value="attr2"></asp:ListItem>
            <asp:ListItem Value="attr3"></asp:ListItem>
        </asp:DropDownList>
    </td>
    <td>
        <asp:DropDownList ID="ddl_BoxComparision" runat="server">
            <asp:ListItem Value="=" Selected="true"></asp:ListItem>
            <asp:ListItem Value=">"></asp:ListItem>
            <asp:ListItem Value="<"></asp:ListItem>
            <asp:ListItem Value="Like"></asp:ListItem>
            <asp:ListItem Value="!="></asp:ListItem>
        </asp:DropDownList>
    </td>
    <td>
        <asp:TextBox ID="btn_boxval" runat="server" ></asp:TextBox>

    </td>
    <td>
        <asp:CheckBox ID="chk_DeleteBoxRow" runat="server" />
    </td>
</tr>

I then add a CSS rule like so:

#TemplateRow { display:none; }

Now we have a row that we can use as a template for adding new rows, and the actual markup for the template can still be generated by .NET. It is important to note that when using this approach with a table, the template row needs to be inside the table to which you'll be appending the rows, in order to ensure that the cells are the appropriate width.

The last bit of markup we'll need to do is to give the table an ID, so that we can manipulate the rows in our script. I chose "BoxTable".

Now, let's construct our script. Because you are using .NET, it's important to remember that for any tag with the runat="server" attribute, the ID attribute that is generated is not the same as the one you assign in the control's ID field. An easy workaround for that is to do something like the following:

var myClientID = '<%= myServerID.ClientID() %>';

The server then outputs the client ID into a string for easy use in your script.

With that in mind, here's our script:

var btn_AddAttr = '<%= btn_AddAttr.ClientID() %>';

$(function() {
    //attach the a function to the click event of the "Add Box Attribute button that will add a new row
    $('#' + btn_AddAttr).click(function() {
        //clone the template row, and all events attached to the row and everything in it
        var $newRow = $('#TemplateRow').clone(true);

        //strip the IDs from everything to avoid DOM issues
        $newRow.find('*').andSelf().removeAttr('id');

        //add the cloned row to the table immediately before the last row
        $('#BoxTable tr:last').before($newRow);

        //to prevent the default behavior of submitting the form
        return false;
    });

    //attach a remove row function to all current and future instances of the "remove row" check box
    $('#DeleteBoxRow').click(function() {
        //find the closest parent row and remove it
        $(this).closest('tr').remove();
    });

    //finally, add an initial row by simulating the "Add Box Attribute" click
    $('#' + btn_AddAttr).click();
});

I think the comments are pretty thorough, but a brief explanation of a few points is warranted:

First, when we clone the template row, we are passing a boolean to the clone function. This says that in addition to the DOM elements we are cloning, we should also clone the event handlers attached to those elements, and attach them to the new clones. This is important in order for the "Delete Row" checkbox to work.

Second, when we clone the template row, we are also cloning all the attributes of all the elements, including the IDs. We don't want this because it violates XHTML compliance and my cause problems. Thus, we strip all the cloned elements of their IDs.

Lastly, because you are using a submit button, it's important to remember to return false in the button's click event, to avoid having it submit the form and cause a postback.

Hopefully this answers your question. One final thing to bear in mind is that since you are creating all these rows with jQuery, the server will not have objects ready to receive the values of the inputs. If you need the server to have access to that information, you'll have to figure out so method of sending it that information.

Ender