Object reference not set to an instance of an object - javascript

i am stuck with this error since last few hours.. i dont know what am i doing wrong here..
<script type="text/javascript">
function viewProfile(index)
{
var GridID = document.getElementById("PersonGridView");
var row=GridID.rows[parseInt(index)+1];
window.open('detailsid.aspx?'+row);
}
</script>
<Columns>
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Last Name" DataField = "LastName" />
<asp:BoundField HeaderText="HomePhoneNumber" DataField="HomePhoneNumber" />
<asp:TemplateField HeaderText="ViewDetails">
<ItemTemplate>
<asp:Button ID="Deatils" runat="server" Text="Details" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Actions">
<ItemTemplate>
<asp:Button ID="Modify" runat="server" Text="Modify" />
<asp:Button ID="Delete" runat="server" Text="Delete" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<FooterStyle BackColor="#CCCC99" />
<PagerStyle BackColor="#F7F7DE" ForeColor="Black" HorizontalAlign="Right" />
<SelectedRowStyle BackColor="#CE5D5A" Font-Bold="True" ForeColor="White" />
<HeaderStyle BackColor="#6B696B" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
</div>
</form>
<p> Code Behind :
protected void PersonGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var ID = PersonGridView.DataKeys[e.Row.RowIndex]["ID"].ToString();
Button btnDetails = (Button)FindControl("Details");
Button btnModify = (Button)FindControl("Modify");
Button btnDelete = (Button)FindControl("Delete");
btnModify.CommandName = "Modify";
btnDelete.CommandName = "Delete";
btnDetails.CommandName = "Details";
btnDelete.CommandArgument = btnModify.CommandArgument = string.Format("{0}", ID);
btnDetails.Attributes["onclick"] = string.Format("viewProfile({0}); return false;", ID);
}
}

Change
var ID = PersonGridView.DataKeys[e.Row.RowIndex]["ID"].ToString();
if (e.Row.RowType == DataControlRowType.DataRow)
{
to
if (e.Row.RowType == DataControlRowType.DataRow)
{
var ID = PersonGridView.DataKeys[e.Row.RowIndex]["ID"].ToString();
i.e. extract the DataKeys only when the row is of DataRow and not for Header/Footer etc.

Is this the line that's throwing the error?:
var ID = PersonGridView.DataKeys[e.Row.RowIndex]["ID"].ToString();
This line is referencing an array item by index in two different places, so you'll need to do a little debugging to determine which one is the problem. Basically, either PersonGridView.DataKeys[] doesn't have an index which matches e.Row.RowIndex or that item doesn't have an index which matches "ID". You'll need to either step through a debugger to examine those values at runtime or toss in some debugging code (Response.Write statements and such to examine values) to see what's going on.
One common error is that the DataGridView is running this code on non-data rows. Header, footer, etc. You can expand the scope of the if statement to address that. Reference the indexes within the conditional rather than outside of it.
Edit: (In response to your comment below)
Is btnDetails set to an instance of an object? I'm guessing it isn't. You'll need to continue the debugging and see if the control you're trying to find is actually there. I notice that it's in a separate ItemTemplate and TemplateField from the other buttons. Is that causing an issue perhaps? I'm not entirely familiar with these server controls so I'm not sure off-hand.
I should take a moment to point out that your code here is very fragile. The problems you've been experiencing are the result of this. You're referencing arrays by indexes manually, including the use of a "magic string" to reference them. You might want to toss in some error checking for that. You're also casting and later using objects without checking if they exist first. FindControl can very easily return a null reference, such as when the control isn't found.
Throwing in tons of error checking is kind of part of the reality of using these web forms controls and their old data binding methods. A lot of extra code, but that's how it goes with these controls and directly binding to weakly-typed DataSets and such.

Related

In ASP.NET Web Forms I want to get control inside child Repeater with javascript

I have Parent repeater which contains another child repeater.
For simplicity let's say that the child repeater contains text box and Requiredvalidator.
Simple example of the markup:
<asp:Repeater ID="rpt1" runat="server">
<HeaderTemplate>
....
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="lbl1" runat="server" CssClass=".."></asp:Label>
<div class="..">
<asp:Repeater ID="rpt2" runat="server">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<div class="...">
<asp:TextBox ID="txt21" runat="server" CssClass="..." MaxLength="7" CssClass="ErrorMessage" ErrorMessage="*" />
<asp:RequiredFieldValidator ID="rfv21" runat="server" CssClass="ErrorMessage" ErrorMessage="*" />
</div>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
</div>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
I create a method like this to get the second repeater's RequiredField id:
function getId(){
var myId = document.getElementById('<%= rfv21.ClientID %>');
}
but of course it didn't work and there was an exception:
The name control-name Does Not Exist in the Current Context
So how can i do this?
I want to mention that the business need for me is that when the onchange, onkeyup, onkeydown events fires for the txt21 it will get it's equivalent rfv21 and enbale it:
I create this method which fires for onchange, onkeyup, onkeydown events changed:
function txt21_onChange(txtbox) {
var newValue = this.value;
var oldValue = this.oldvalue;
var myRfv2 = document.getElementById('<%= rfv2.ClientID %>');
if (newValue != oldValue) {
ValidatorEnable(myRfv2, true);
}
}
and i update txt21 to be:
<asp:TextBox ID="txt21" runat="server" CssClass=".." MaxLength="7" onkeyup="javascript: txt21_onChange(this);this.oldvalue = this.value;" />
but this line want work:
var myRfv2 = document.getElementById('<%= rfv2.ClientID %>');
as i explained before.
I think Item.FindControl(..) may help but how can we use it in this case?
You can bind the javascript function call from Repeater Repeater.ItemDataBound event.
Code Bahind
void R1_ItemDataBound(Object Sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
TextBox txt21 = (TextBox)e.Item.FindControl("txt21");
RequiredFieldValidator rfv21 = (RequiredFieldValidator)e.Item.FindControl("rfv21");
txt21.Attributes.Add("onclick", "txt21_onChange('" + txt21.ClientID + "','" + rfv21.ClientID + "'" )
}
}
Javascript
function txt21_onChange(txt21ID, rfv21ID)
{
txt21ID = document.getElementById(txt21ID);
rfv21ID = document.getElementById(rfv21ID);
//The above are TextBox and RequiredFieldValidator objects of row of TextBox that triggered change event.
//You can use these object
}
The problem here is that there going to be many such controls, one per each row of each child repeater. All will have slightly different generated IDs. So instead of querying them by id (impossible), you can use jQuery to quickly find them relatively to the txt that fired an event:
function txt21_onChange(txtbox) {
var rfv2 =
$(textbox) // gives you the jquery object representing the textbox
.closest("div") // the parent div
.find("id*='rfv2'"); // the element you are looking for, id contains rfv2
This answers the immediate question in this thread on how to get hold of the element. But I am not sure it will solve your bigger problem of enabling/disabling validation. You cannot easily do so with server side controls in javascript. Besides, validator is not disabled by default in your code. Although I believe all this is worth a separate question here on SO>

Telerik RadGrid how to display confirmation message

I have <telerik:RadGrid/>
inside this grid i have the following column contains button
<telerik:GridTemplateColumn >
<ItemTemplate>
<asp:Button ID="btnDelete" runat="server" Text="Delete"
CommandArgument='<%#Container.ItemIndex%>' OnCommand="btnDelete_Command">
protected void btnDelete_Command(object sender, CommandEventArgs e)
{
Telerik.Web.UI.GridDataItem item = gvAllDocuments.Items[int.Parse(e.CommandArgument.ToString())];
string FileName = item["documentFileName"].Text;
}
how I can add confirmation message before function btnDelete_Command executing ..
Do not use ItemIndex. It is just a row index of the grid. Instead, you want to set unique id inside DataKeyNames.
Ideally, you do not want to implement your own delete button, because telerik already has delete button which calls OnDeleteCommand automatically.
It is a prefer way of doing it for RadGrid.
<telerik:RadGrid ... OnDeleteCommand="RadGrid_DeleteCommand">
<MasterTableView DataKeyNames="xxxId" ...>
<Columns>
<telerik:GridButtonColumn
ButtonType="ImageButton"
ConfirmText="Are you sure you want to delete?"
CommandName="Delete"
ImageUrl="~/Images/Delete.png"
Text="Click to delete" UniqueName="Delete">
</telerik:GridButtonColumn>
</Columns>
...
</MasterTableView>
</telerik:RadGrid>
protected void RadGrid_DeleteCommand(object source, GridCommandEventArgs e)
{
int id = Convert.ToInt32(
e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["xxxId"]);
// Delete logic here.
}

Checking all checkboxes in ASP.NET Gridview, multiple tables on the same page

Alright, so there is tons of documentation out there that I have filed through and attempted many times throughout the day and can not seem to nail this issue down. I have multiple Gridviews on one page (inside of collapsible panels), of which two have a column (the 7th column, from 0) that contains checkboxes. I want to enable the user to select/deselect all of the checkboxes using a checkbox field in the header row. I prefer to accomplish this using Javascript, but can't seem to be able to get there. This is the way I prefer to go since it seems that it would work with multiple tables on the page (correct me if I am wrong). Using Firebug, there were no errors, it just simply isn't working and I can't find out why.
Here is my ASP.NET code:
<asp:GridView ID="gvSerialNumberDetails" CellPadding="5" runat="server" CssClass="wind" AutoGenerateColumns="false">
<HeaderStyle CssClass="windHeader" />
<Columns>
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:BoundField DataField="Serial Number" HeaderText="Serial Number" />
<asp:BoundField DataField="Facility" HeaderText="Facility" />
<asp:BoundField DataField="Department" HeaderText="Department" />
<asp:BoundField DataField="EmpID" HeaderText="EmpID" />
<asp:BoundField DataField="Configuration" HeaderText="Config" />
<asp:BoundField DataField="Error" HeaderText="Errors" />
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="chkHeader" ToolTip="Select All" runat="server"
onclick="changeAllCheckBoxes(this)" />
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox ID="chkItem" runat="server" ToolTip="Select this item" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And here is my Javascript:
<script type="text/javascript" language="javascript">
function changeAllCheckBoxes(sender) {
var gridViewRows = GetParentElementByTagName(sender, "table").rows;
for (var i = 1; i < gridViewRows.length; ++i) {
gridViewRows[i].cells[7].childNodes[0].checked = sender.checked;
}
}
function GetParentElementByTagName(element, tagName) {
var element = element;
while (element.tagName != tagName)
element = element.parentNode;
return element;
}
</script>
UPDATE
Alright, so I AM getting an error now. "TypeError: element is null [Break On This Error] </tr><tr>" How do I go about fixing this? It seems like it should climb up the DOM and find the table element, but doesn't.
Please try below javascript function insdead of yours. I check this functions and it work perfect in my code. Let me know if you find any difficulty.
function changeAllCheckBoxes(objparentcheckbox)
{
var HeaderCheckboxControl = objparentcheckbox
var table = getParentByTagName(HeaderCheckboxControl, 'table');
//get all the control of the type INPUT in the base control.
var Inputs = table.getElementsByTagName("input");
for(var n = 0; n < Inputs.length; ++n)
if(Inputs[n].type == 'checkbox')
{
Inputs[n].checked = HeaderCheckboxControl.checked;
}
return false;
}
function getParentByTagName(obj, tag)
{
var obj_parent = obj.parentNode;
if (!obj_parent) return false;
if (obj_parent.tagName.toLowerCase() == tag) return obj_parent;
else return getParentByTagName(obj_parent, tag);
}
Jquery Alternation for above method is as below:
function changeAllCheckBoxes(objparentcheckbox)
{
if(objparentcheckbox.checked)
$(objparentcheckbox).closest('table').find('input[type=checkbox]').attr('checked', 'checked');
else
$(objparentcheckbox).closest('table').find('input[type=checkbox]').removeAttr('checked', 'checked');
}
here i add jsfiddle link for demo : Demo link

Modify text values in datagrid returned by SELECT command

I would like to modify the text values after the data has been returned from the database, I need to modify the MBS1270 and the MBS1263 to look like the others when displayed in the datagrid.
SelectCommand="SELECT PartNumber as 'Part Number', OnhandStockLevel as 'In Stock', DueIn as 'In Production' FROM vw_Rb_FreeStock WHERE PartNumber = 'UFP-0390B' OR PartNumber = 'UFP-0690B' OR PartNumber = 'MBS1270' OR PartNumber = 'MBS1263'">
Now, I have used the javascript to replace the values in body load, however, this messes up the sorting of the datagrid and makes the new replaced values appear on top still, because 'M' comes before 'U', and it still sorts based on the old value.
Javascript:
<script type="text/javascript">
function modText(original, replace) {
alert("Hello");
var find = original;
var repl = replace;
var page = document.body.innerHTML;
while (page.indexOf(find) >= 0) {
var i = page.indexOf(find);
var j = find.length;
page = page.substr(0, i) + repl + page.substr(i + j);
document.body.innerHTML = page;
}
</script>
I want to replace the MBS values with values 'UFP-1690B' and 'UFP-1290B'.
Is there any way to sort based on the replaced values? Or is there another approach I could take?
I tried to do something similar as to how you replace the column header using the 'AS' sql function but that failed, something like that would be perfect.
And no, I can't change the raw database value.
Gridview code:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
BackColor="White" BorderColor="#999999" BorderStyle="None" BorderWidth="1px"
CellPadding="3" CssClass="style1" DataKeyNames="Part Number"
DataSourceID="SqlDataSource1" GridLines="Vertical">
<RowStyle BackColor="#EEEEEE" ForeColor="Black" />
<Columns>
<asp:BoundField DataField="Part Number" HeaderText="Part Number"
ReadOnly="True" SortExpression="Part Number" />
<asp:BoundField DataField="In Stock" DataFormatString="{0:0}"
HeaderText="In Stock" SortExpression="In Stock" />
<asp:BoundField DataField="In Production" DataFormatString="{0:0}"
HeaderText="In Production" ReadOnly="True" SortExpression="In Production" />
</Columns>
<FooterStyle BackColor="#CCCCCC" ForeColor="Black" />
<PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />
<SelectedRowStyle BackColor="#008A8C" Font-Bold="True" ForeColor="White" />
<HeaderStyle BackColor="#000084" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="#DCDCDC" />
</asp:GridView>
A month has been since this, but thought I'd add a final answer for anyone else with a similar problem.
I used the SQL REPLACE function, see: http://msdn.microsoft.com/en-us/library/ms186862.aspx
After that I combined the original data with the replaced data using UNION.
Final code:
SELECT REPLACE(REPLACE(PartNumber, 'MBS1269', 'UFP-1290S'), 'MBS1262', 'UFP-1690S') AS PartNumber... (and so on)
Output was absolutely perfect.
You can try with RowDataBound event
void GridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[1].Text = e.Row.Cells[1].Text.Replace("MBS","UFP");
}
}
You can add this to your Grid
<asp:gridview onrowdatabound="GridView_RowDataBound" />

Pass a gridview column value to a session using javascript

I have a gridview that contains a list of products. What i am trying to do is using the ItemTemplate is pass the ProductID of the selected item using an Onclick event to a session so i can then lookup that session on another page to avoid having the ProductID shown in the URL.
<asp:GridView ID="GVProducts" runat="server"
onselectedindexchanged="GVProducts_SelectedIndexChanged">
<Columns>
<asp:ImageField DataImageUrlField="FileName"
DataImageUrlFormatString="Images/{0}" HeaderText="Image">
<ControlStyle Height="80px" Width="80px" />
</asp:ImageField>
<asp:TemplateField HeaderText="Title" SortExpression="ProductID" >
<ItemTemplate>
<a onclick="javascript:function setSessionVariable(<%#Eval("ProductID")%>)" href="ProductDetail.aspx"><%#Eval("Title")%></a>
</ItemTemplate></asp:TemplateField>
</Columns>
<FooterStyle BackColor="#99CCCC" ForeColor="#003399" />
<HeaderStyle BackColor="#003399" Font-Bold="True" ForeColor="#CCCCFF" />
<PagerStyle BackColor="#99CCCC" ForeColor="#003399" HorizontalAlign="Left" />
<RowStyle BackColor="White" ForeColor="#003399" />
<SelectedRowStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
<SortedAscendingCellStyle BackColor="#EDF6F6" />
<SortedAscendingHeaderStyle BackColor="#0D4AC4" />
<SortedDescendingCellStyle BackColor="#D6DFDF" />
<SortedDescendingHeaderStyle BackColor="#002876" />
</asp:GridView>
Hopefully it is something simple as i am just starting out with javascript but i cant seem to get it to pass to the session.
Thanks
If you have jQuery library in your project, you may use jQuery ajax to send data to server pages.
function setSessionVariable(selectedval)
{
$.post("yourserverpage.aspx", { productId : selectedval },function(data){
alert("set to session!");
});
}
and create an aspx page called youserverpage.aspx and read the querystring value in the page load and set to session.
Call a web method from your javascript (using jQuery) and set the session on the web method:
public partial class _Default : Page
{
[WebMethod]
public static void SetVar(string myVar)
{
Session["var"] = myVar;
}
}
jQuery:
$.ajax({
type: "POST",
url: "Default.aspx/SetVar",
data: "{'myVar':'SessionVarValueSetOnJavascript'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
// Do something interesting here.
}
});
See this page for a nice example
Setting Session should be done in ServerSide. Try this
Markup
<asp:TemplateField HeaderText="Title" SortExpression="ProductID" >
<ItemTemplate>
<asp:LinkButton ID="MyLink" runat="server"
CommandName="SendID"
CommandArgument='<%#Eval("ProductID")%>'>
<%#Eval("Title")%>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
Code-Behind
protected void GVProducts_RowCommand(object sender, GridViewCommandEventArgs e)
{
// If multiple buttons are used in a GridView control, use the
// CommandName property to determine which button was clicked.
if (e.CommandName == "SendID")
{
// Get the ProductID stored in the CommandArgument
// property to an String.
string clickedProductID = e.CommandArgument.ToString();
// Set that ProductID to Session
Session["ProductID"] = clickedProductID;
// Redirect to the newpage.
Response.Redirect("ProductDetails.aspx");
}
}
Please dont forget to add OnRowCommand="GVProducts_RowCommand" to the GridView markup.
Update:
<asp:GridView ID="GVProducts" runat="server"
OnRowCommand="GVProducts_RowCommand">

Categories

Resources