Retrieve previous and next rows in a table using jQuery - javascript

I am using ASP.NET to create a page with a GridView that is very editable for the end user. Basically, all rows contain TextBoxes (instead of static text) which the user can edit whenever he wants. No postback occurs ever, except when he clicks the Save button on the bottom of the page. Then, I loop through each row in the grid, retrieve the values in the controls in each row and save them back to the database.
I am now trying to implement swapping two rows (to move a row up or down) in Javascript, and for that I need some way to retrieve the previous and next rows in a table.
At the moment my GridView contains a HiddenField as the first column, which contains the unique Id of the data item (I need this to store it back to the database of course). For other purposes (deleting a row) I have figured out how to retrieve this Id, which is this:
var itemHf = $(this).parent().parent().parent().find(':input');
There's so many 'parent' calls because this happens in the click event of an Image, which is inside a LinkButton, which is inside the last column of my grid. So the first parent is the LinkButton, the next is the table cell, and finally the table row. Then, I suppose the find(':input') function returns the first input element in this row (which in my case is the hidden field that contains the id).
So, using the same method I can get the current row:
var row = $(this).parent().parent().parent();
But how do I get the previous and next rows?
Also, once I have those rows, I will need to retrieve values from more input elements. I know I can find the first one using find(':input'), but how do I find the second and the third input elements in this table row?
EDIT
I don't have any html at this time but here is the ASP.NET markup for the grid:
<asp:GridView runat="server" ID="grid" AutoGenerateColumns="False"
onrowcommand="grid_RowCommand" onrowdeleting="grid_RowDeleting">
<Columns>
<!-- Move Up button -->
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" OnClientClick="return false;">
<asp:Image ImageUrl="~/Images/moveUp.png" AlternateText="moveUp" runat="server" CssClass="moveUp" ID="moveUp" />
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<!-- Move Down button -->
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" OnClientClick="return false;">
<asp:Image ImageUrl="~/Images/moveDown.png" AlternateText="moveDown" runat="server" CssClass="moveDown" ID="moveDown" />
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<!-- ID Hidden Field -->
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField runat="server" Value='<%# DataBinder.Eval(Container.DataItem, "Id") %>' />
</ItemTemplate>
</asp:TemplateField>
<!-- Name textbox field -->
<asp:TemplateField HeaderText="Naam">
<ItemTemplate>
<asp:TextBox runat="server" Width="200px" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</ItemTemplate>
</asp:TemplateField>
<!-- Price textbox field -->
<asp:TemplateField HeaderText="Prijs">
<ItemTemplate>
<asp:TextBox runat="server" Width="50px" Text='<%# DataBinder.Eval(Container.DataItem, "Price") %>' />
</ItemTemplate>
</asp:TemplateField>
<!-- Delete button -->
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" OnClientClick="return false;">
<asp:Image ImageUrl="~/Images/delete.png" AlternateText="delete" runat="server" CssClass="delete" ID="delete" />
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And here is an example of the jQuery I'm using:
$(document).ready(function () {
$('table td img.delete').click(function () {
var id = $(this).closest('tr').find(':input').val();
alert(id);
});
});

You can access the row by doing this:
var row = $(this).closest('tr');
Now that you have the row, you can get the next/pre row by doing this:
var next = row.next();
var prev = row.prev();
To switch the rows around, you can use .detach() and .appendTo()

I figured it out. Once I got a row (either the current row or the previous row), I can find the first input element using the same format as before. Then I can find the closest cell ('td'), call next() on that and then find the first input element again:
var row = $(this).closest('tr');
var idInput = row.find(':input');
var nextInput = idInput.closest('td').next('td').find(':input');
There might be a better way, but this works so I'm happy with it for now.
Thanks for your help, for some reason I can never quite grasp the concepts of jQuery...

As far as I understand your post var row = $(this).parent().parent().parent(); could be replaced with
var row = $(this).parents("tr");
Furthermore var itemHf = $(this).parent().parent().parent().find(':input'); would probably better be expressed as
var itemHf = $(this).parents('tr').find('input:first');
So, to get the previous row you would use
var prevHf=$(this).parents('tr').prev().find('input:first');
and the next row would be
var nextHf=$(this).parents('tr').next().find('input:first');

Related

ASPx.Net How to catch a change in value in an Itemtemplate DDL

I'm struggling to find a way to solve this.
I have a gridview and the first column of it is a DropDownList defined in an Itemtemplate:
<asp:GridView ID="gvXYZ" runat="server" DataKeyNames="Serial, XYZValue">
<Columns>
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:DropDownList ID="ddlStat" runat="server" OnSelectedIndexChanged="ddlStat_SelectedIndexChanged"><asp:ListItem> </asp:ListItem><asp:ListItem> </asp:ListItem><asp:ListItem>OK</asp:ListItem><asp:ListItem>NG</asp:ListItem></asp:DropDownList>
</ItemTemplate>
<FooterStyle HorizontalAlign="Center" VerticalAlign="Middle" Wrap="False" />
<HeaderStyle HorizontalAlign="Center" VerticalAlign="Middle" Wrap="False" />
<ItemStyle HorizontalAlign="Center" VerticalAlign="Middle" Wrap="False" />
</asp:TemplateField>
</Columns>
</asp:GridView>
The user is presented with an empty choice, OK or NG as possible selections.
How can I trigger either JavaScript or VB side to run a function when the user makes any selection in any of the DDL in the grid?
In order to complete what asked, the user has to have either OK or NG selected.
I'm trying to tie the Save button to the fact that the grid has been completed.
I know I can run JavaScript on a HTML dropdown so I tried to create a function to do it and from an article I found I tried to run a VB method from a javascript function:
function ddlStat_SelectedIndexChanged() {
var someValueToPass = 'Hello server';
__doPostBack('CustomPostBack', someValueToPass);
}
the script never runs, the postback does not occur and the VB side code:
Protected Sub ddlStat_SelectedIndexChanged(sender As Object, e As EventArgs)
Dim x As Integer
For x = 1 To 10 : x = x + 1 : Next
End Sub
is never triggered either.
I thought to do this on the VB side because I think I can more easily access properties of the grid, like the number of rows so I can check the DDL in each one of them.
Thank you for this and ask questions if I wasn't clear.
Setting AutoPostback property of the drop down should raise a post back call to the server side. JS function can be called using the HTML event onchange
<asp:DropDownList ID="MyDropDown" runat="server" AutoPostBack="True"
OnSelectedIndexChanged="SelectedChange" onchange="YourChangeFun(this);">
</asp:DropDownList>
Javascript:
<script type="text/javascript">
function YourChangeFun(ddl)
{
alert(ddl.selectedIndex);
}
</script>

send clientid of another control to javascript via anchor tag

I have gridview in asp.net as:
<asp:TemplateField HeaderText="Shipment Received" ItemStyle-VerticalAlign="top" HeaderStyle-VerticalAlign="top">
<ItemTemplate>
<a href="#" id="aShipment" onclick="javascript:setIdRMA('<%# Eval("idRMA") %>','<%# Eval("idreturn")%>','<%# Eval("idorder")%>','<%# Eval("returnReason")%>','<%# Eval("returnFor")%>','<%# Eval("returnStatus")%>','<%# Eval("dateClosed")%>','<%# Eval("shipmentReceiveDate")%>','<%# Eval("resolution")%>','<%# Eval("sku") %>',lblShipmentReceived.ClientID);">
<asp:Label ID="lblShipmentReceived" runat="server" Text='<%# Bind("shipmentReceived")%>'></asp:Label>
</a>
</ItemTemplate>
</asp:TemplateField>
on click of anchor tag i am calling setIdRMA method of javascript
I want to send client id of label inside anchor tag to that function.
For that i written as shown in above:
lblShipmentReceived.ClientID
But this does not get passed.
Please help me.
Since you are using GridView you may not get ClientID directly, you can find label which is inside anchor tag by its relative referrance. First pass achor tag element by this keyword and access it in the function to find label.
onclick="setIdRMA(..,..,..,this);"
and in the function
function setIdRMA(..,..,..,obj)
{
var label = $(obj).find('span'); //asp.net label is rendered as span and there is only 1 label so you can use .find()
}
Use .children selector for this
And asp:Lable rendered as span on HTML page so you can find it by using span
<asp:TemplateField HeaderText="Shipment Received" ItemStyle-VerticalAlign="top" HeaderStyle-VerticalAlign="top">
<ItemTemplate>
<a href="#" id="aShipment" onclick="javascript:setIdRMA(this,'<%# Eval("idRMA") %>','<%# Eval("idreturn")%>','<%# Eval("idorder")%>','<%# Eval("returnReason")%>','<%# Eval("returnFor")%>','<%# Eval("returnStatus")%>','<%# Eval("dateClosed")%>','<%# Eval("shipmentReceiveDate")%>','<%# Eval("resolution")%>','<%# Eval("sku") %>',lblShipmentReceived.ClientID);">
<asp:Label ID="lblShipmentReceived" runat="server" Text='<%# Bind("shipmentReceived")%>'></asp:Label>
</a>
</ItemTemplate>
</asp:TemplateField>
Change your onclick function argument and add this as first argument in your JavaScript function and then change your javaScript function as below .
function setIdRMA(,,,){
alert($(this).children('span').attr('id'));
}

Populating existing dropdownlist using AsyncPostBackTrigger, not populate a new dropdownlist

For my web app, I tried to populate dropdownlist (DDL) based on what client click on the calendar extender ( I have this declared in codebehind vb.net to load it from database) using AsyncPostBackTrigger (because I dont want the page to autopostback). I have the button to fire the date selected and it did worked to populate the DDL except not really the way I wanted it to. Instead of updating it in the existing DDL, it creates a new DDL besides the existing ones. I tried looking for solution but did not managed to find any. Anyone can help me figure out why this happens and how to fix this?
Here's my asp.net & javascript code
<asp:Label ID="label16" runat = "server" Text="Select the date"></asp:Label></td>
<td id="Td29" style="width:290px;" runat="server">
<asp:TextBox ID="tbPostingDt" runat="server" style ="width:174px;"></asp:TextBox>
<asp:Button ID="ClickBtn" runat="server" Text="Click" style="display:none" OnClick="ClickBtn_Click" />
<asp:ImageButton ID="CalendarBtnPostingDt" runat="server" ImageUrl="~/Images/Calendar_scheduleHS.png" AlternateText="Click to display calendar"/>
<cc1:CalendarExtender ID="calPost" runat="server" PopupButtonID="CalendarBtnPostingDt"
TargetControlID="tbPostingDt" OnClientDateSelectionChanged="dateSelectionChanged" Format="dd-MMM-yyyy" Enabled="True"></cc1:CalendarExtender></td>
<asp:UpdatePanel ID="UpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="label18" runat = "server" Text="Post Cycle No"></asp:Label></td>
<td id="Td33" style="width:290px;" runat="server">
<asp:DropDownList ID = "ddlPostCycleNo" runat = "server" style ="width:180px;">
<asp:ListItem>ALL</asp:ListItem>
</asp:DropDownList> </td>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ClickBtn" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
function dateSelectionChanged(sender, args) {
var PostingDt = document.getElementById('<%= tbPostingDt.ClientID%>').value.trim();
var clickButton = document.getElementById("<%= ClickBtn.ClientID %>");
clickButton.click();
}
nevermind I figured it out already. I used the ontextChanged for the textbox when user select the date from calendar, and removed OnClientDateSelectionChanged, triggers and dummy button. I keep the UpdatePanel and it works just the way I wanted.

How to query asp button text in gridview to see if any have a certain text value

I now have an asp button in a gridview which I can toggle the text from "Add" to "Remove". Now what I would like is either jquery or javascript to loop through all the rows (or inquire all rows) to determine if any buttons have been toggled (they would have text of "Remove" since the default is "Add"). I don't necessarily need to loop through and process anything, I just want to hide a div if no buttons have been toggled to text of "Remove". The user may have toggled the buttons to "Remove" and back to "Add". So I need to know if at least one button text is currently "Remove".
Here is my templated asp button definition:
<asp:TemplateField HeaderText="Prior <br /> Downld" HeaderStyle-ForeColor="White" >
<ItemTemplate >
<asp:Button id="btnBuy" runat="server" OnClientClick="btnBuyToggle(this); return false;" Text="Add" CssClass="buyButton" Visible='<%# Eval("SORD_ShowBuyButton") %>' />
</ItemTemplate>
<HeaderStyle Width="7%" />
<ItemStyle CssClass="sessionOrderDownloadItems" VerticalAlign="Middle" HorizontalAlign="Center" />
</asp:TemplateField>
Anyway, I am hoping for maybe a jquery selector looking for text = "Remove", but I am not sure how to construct it.
Note: Working result is this:
if ( $("input[value=Remove]").length == 0 ) {
$(".divDownloadHeaderClass").show();
$(".divPurchaseHeaderClass").hide();
}
}
I think this would work:
if ( $("input[value=Remove][type=submit]").length > 0 ) {
$(".divDownload").hide();
}
Hope it helps!

Asp.net dynamic gridview with dropdownlists

I have a dynamic (allows addition of rows on the fly) an ASP gridview that has a dropdownlist in one of its columns. I would like to take an action enable/disable the textbox in the column after depending on the selection in the dropdownlist during data entry.
Any help will be highly appreciated.
You can do this easily with jQuery. With a bit of modification, you can get it working exactly as you want it to.
First, add the following to your <head> tag:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$(".ddlClass").change(function () {
var txt = $(this).closest("tr").find(".txtClass");
if ($(this).val() == 0) {
txt.css("background", "#cccccc");
txt.attr("disabled", "disabled");
}
else {
txt.css("background", "#ffffff");
txt.attr("disabled","");
}
});
});
Next, create your gridview and add template columns for your textbox and dropdown list. In the code below, notice that the dropdown list has been given a class "ddlClass" and the textbox has been given a class "txtClass". You can change these as you see fit.
<asp:gridview runat="server" ID="gvw" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="field1" />
<asp:BoundField DataField="field2" />
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:TextBox runat="server" ID="txtName" CssClass="txtClass"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<select class="ddlClass">
<option value="1">Enabled</option>
<option value="0">Disabled</option>
</select>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:gridview>
The .ready function attaches a click event to each dropdownlist with the class "ddlClass". When changed, the code will find the textbox with the class "txtClass" in the same row as the dropdownlist and then enable/disable accordingly.
Well you can use Javascript if you are familiar with that. I recommend using JQuery since its a query language for transversing through the DOM.
But if you are not familiar with Javascript then I recommend adding a SelectionChangedEvent on your DropDownList and then in the code behind for your page in the SelectionChangedEvent handler:
Cast the sender object to a DropDownList and then get the parent of that object which would be the GridViewRow.
With that GridViewRow you can use the FindControl method to get a reference to the TextBox in the same row and then you can enable it or disable it.
If you dont like the page refresh (post-back) everytime they change a selection in your dropdownlist then wrap your grid in an UpdatePanel.
Let me know if you are having a hard time with this and I'll post code to 1 of the above solutions. Just let me know which one you are most comfortable with.

Categories