Hiding the Null Fields - asp.net

I have a data repeater that is reading a few different fields. However, some information being pulled is empty. I would like to hide these fields in this case.
I am not sure how best to go about this. I have tried the following methods:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:db %>"
SelectCommand="SELECT GrName, GrRoom
FROM [Group] WHERE GrName LIKE 'A%' ORDER BY GrName && * IS NOT NULL">
</asp:SqlDataSource>
<!-- output to page -->
<div data-role="collapsible-set">
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<ItemTemplate>
<div data-role="collapsible" data-collapsed="true">
<p>Room: <%# Eval("GrRoom")%></p>
</div>
</ItemTemplate>
</asp:Repeater>
Or, do I do something like this in the head?
<script type="text/vbscript">
If (GrRoom = NULL) Then
display: none;
End If
</script>
I'm not sure I'm grasping this concept right now. Basically, I want the following to function to run as:
"If GrRoom is empty, do not display"
Any thoughts on this? I appreciate your insight. I'm relatively new to ASP and .NET, so I'm still learning a lot.
Thank you for your time and help.

<ItemTemplate>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"
Visible='<%# Not [String].IsNullOrEmpty(If(TypeOf Eval("GrRoom") Is DbNull, [String].Empty, DirectCast(Eval("GrRoom"), String))) %>'>
<div data-role="collapsible" data-collapsed="true">
<p>
Room:
<%# Eval("GrRoom")%></p>
</div>
</asp:PlaceHolder>
</ItemTemplate>
Edit
I didn't test it at first, now I've properly tested this code. I'm also checking now and for empty strings. Please try it.
Edit 2
I was using C# syntax, sorry, now is edited with VB
Edit 3
I added and the DbNull check

If your objective is not to retrieve the data at all where the field is null, your SQL syntax is close but needs a tweak:
SELECT GrName, GrRoom
FROM [Group]
WHERE GrName LIKE 'A%'
AND IsNull(GrRoom, '') <> ''
ORDER BY GrName
"* is not null" is not valid - IS NOT NULL must refer to a single value, and * refers to all columns in the collected tables utilized in the result set.
&& is also not a valid WHERE construct - you must use "AND" and "OR" not && and ||
Your WHERE conditionals all have to occur before the ORDER BY clause
And finally - Like 'A%' will automatically filter out null values because a null cannot be like something with a value.
So if you use the sql as I've written it, that will ensure that GrName is always populated, and so on your ASP side, logic to show/hide controls isn't necessary.
Of course there are reasons to show/hide controls as well - but if you can eliminate unwanted rows from the data being sent to the server, that's less traffic overall, and "as little as necessary and possible" is always a goal when it comes to data transmission.

Related

ASP.Net DataGrid selectively bound entries

I have less knowledge of ASP.Net. Currently, I am using ASP.Net DataGrid control and mapped all the source information in UI successfully.
myDataGrid.DataSource = MyCollectionOfObjects
myDataGrid.DataKeyField = "MyKey"
myDataGrid.DataBind()
Now, the problem is, I don't want all the objects to be mapped in the grid. Need to do some conditional filtering before mapping. Is there any feature in DataGrid that allow me to decide bind or not bind some objects?
1) One option is mapping the collection(MyCollectionOfObjects) to a new collection that contains only the required objects by applying required filtering but I am not expecting that at this moment.
For example,
foreach(var item in MyCollectionOfObjects)
{
if(item.InvalidEntry)
{
// This entry is not needed
}
else
{
// Okay with this entry
}
}
You could do something like this. Show/Hide a PlaceHolder based on the value of InvalidEntry.
<asp:TemplateColumn>
<ItemTemplate>
<asp:PlaceHolder ID="PlaceHolder2" Visible='<%# Convert.ToBoolean(Eval("InvalidEntry")) %>' runat="server">
<%# Eval("Column1") %>
</asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateColumn>
However, filtering the source data with Linq would be much easier.
myDataGrid.DataSource = MyCollectionOfObjects.Where(x => x.InvalidEntry == false);

__EVENTTARGET Contains Invalid Control ID

Googled variations of the title and everything was related to a null value.
I have an issue where the return value from Page.Request.Params["__EVENTTARGET"] duplicates the unique id of the control.
ctl00$MainContent$ActivityTabset$TabNewActivity$cbxActivityCode$ctl00$MainContent$ActivityTabset$TabNewActivity$cbxActivityCode
cbxActivityCode.UniqueID returns
ctl00$MainContent$ActivityTabset$TabNewActivity$cbxActivityCode
The following is the code that fails in the comparison. It is in the Page_Load event, and is the only code to execute right now if it is a postback.
string controlName = Page.Request.Params["__EVENTTARGET"];
if (cbxActivityCode.UniqueID == controlName)
{
ConfigureActivityUnits();
}
Here is the definition of the control
<obout:ComboBox ID="cbxActivityCode" runat="server"
DataSourceID="ObjectDataSourceDAOActivity"
FilterType="StartsWith" EmptyText="Select..."
AutoPostBack="true"
OnSelectedIndexChanged="cbxActivityCode_SelectedIndexChanged"
AllowCustomText="false" AutoValidate="true" DataValueField="Id"
DataTextField="Description" EnableViewState="true"
OpenOnFocus="true" MenuWidth="425" AllowEdit="False"
Width="300px">
</obout:ComboBox>
I am new to ASP.net and am wondering if it is possible one of the control attributes is causing this behavior?
Is it possibly a bug with the control?
Are there hooks in ASP.net where someone can manipulate a value which will effect Page.Request.Params["__EVENTTARGET"]? (This is a big messy legacy system, and I have no prior developers as a resource.)
If not any of the above, anyone have any ideas as to what could be causing this?

UGC conditional statement is not working

I am using UGC feature of Tridion 2011. I have done almost but stuck in one place. actually, i have to display one text when user have entered comments, it will display if comments are greater then 0. i am using for this condition but it does not go in the condition.
<ugc:ItemStats ItemURI="#PhysicalUri" runat="server">
<ugc:Choose runat="server">
<ugc:When test=" ugcItemStats.numberOfComments equals 0 " runat="server">
html1
</ugc:When>
<ugc:Otherwise runat="server">
html2
</ugc:Otherwise>
</ugc:Choose>
</ugc:ItemStats>
Could any one please help me to resolve his issue
Use this code, i hope will be work.
<%
HttpContext.Current.Item["variable"] = 0;
%>
<ugc:ItemStats ItemURI="#PhysicalUri" runat="server">
<ugc:Choose runat="server">
<ugc:When test="ugcItemStats.numberOfComments equals variable " runat="server">
html1
</ugc:When>
<ugc:Otherwise runat="server">
html2
</ugc:Otherwise>
</ugc:Choose>
</ugc:ItemStats>
The When statement accesses the ugcItemStates object from the HttpContext.Current.Items collection.
I suspect that by nesting the statement in the ItemStats control causes this object not to be available yet.

If/else logic within a table cell using ASP

I'm using an SQL query to gather information from a database and C# + ASP to get it in a table on the front end side. I'm trying to make it so that when I get an item, it will check its value and change the font color it is displayed in based on the value. I'm not sure how the syntax is supposed to work with all the tags so I'm getting weird results. So far it looks like:
<td nowrap valign="top">
if (<%# DataBinder.Eval(Container, "DataItem.StreetNumber")%> == "1") {
<font color = "red"><%# DataBinder.Eval(Container, "DataItem.StreetNumber")%></font>
}
else
<%# DataBinder.Eval(Container, "DataItem.StreetNumber")%></td>
Hopefully that makes some sense.
A simpler way to do it may be something like this:
<font color='<%# Int16.Parse(Eval("StreetNumber").ToString()) == "1" ? "red" : "black" %>' />
Are you using the Repeater control? If so you can handle the ItemDataBound event and do what you like inside it - example

ASP.NET: How to access repeater generated elements from javascript?

i have a series of rows that are generated using an asp:repeater:
<asp:repeater ID="itemsRepeater"
OnItemDataBound="itemsRepeater_ItemDataBound"
runat="Server">
<itemtemplate>
<tr>
<td>
<asp:HyperLink ID="linkView" runat="server"
Text="<%# GetItemText((Item)Container.DataItem) %>"
NavigateUrl="<%# GetViewItemUrl((Item)Container.DataItem) %>" />
</td>
<td>
<asp:HyperLink ID="linkDelete" runat="server"
Text="Delete"
NavigateUrl="<%# GetDeleteUrl((ActionItem)Container.DataItem) %>" />
</td>
</tr>
</itemtemplate>
</asp:repeater>
The repeater creates an HTML table, with each row containing a link to an item and (what is essentially) a "Delete" link. The above simplified example code generates HTML similar to:
<TR>
<TD>
<A href="ViewItem.aspx?ItemGuid={19a149db-5675-4eee-835d-3d78372ca6f9}">
AllisonAngle_SoccerGirl001.jpg
</A>
</TD>
<TD>
Delete
</TD>
</TR>
Now that all works, but i want to convert the "Delete" to client side. i want to be able click the link and it will, on the client javascript:
prompt an alert "Are you sure..."
have javascript issue server-hit to actually delete the item they want
remove the item from the client DOM tree
So there are four problems to be solved:
How to hook up javascript to the client-side click of the Delete link.
How to know what item the user clicked Delete
Prevent a post-back
Delete the row that the user clicked
That is my question.
From here on you will find my rambling attempts to solve it. Don't take anything below as relating in any way to any possible accepted solution. Just because i posted code below, doesn't mean any of it is useful. And it doesn't mean i'm anywhere within spitting distance of the best solution. And because i can't make anything below work - it must have gone down the wrong road.
My Attempts
Wiring Up Javascript
The first task is to convert the delete link HTML from something such as:
<A href="DeleteItem.aspx?ItemGuid={19a149db-5675-4eee-835d-3d78372ca6f9}">
Delete
</A>
into something more javascripty:
<A href="#"
onclick="DeleteItem('DeleteItem.aspx?ItemGuid={19a149db-5675-4eee-835d-3d78372ca6f9}')">
Delete
</A>
and the add the script:
<script type="text/javascript">
//<![CDATA[
function DeleteItem(deleteUrl)
{
//Ask the user if they really want to
if (!confirm("Are you sure you want to delete INSERT NAME HERE?"))
{
return false;
}
//Call returns false if the server returned anything other than OK
if (!DoAjaxHit(deleteUrl)
{
return false;
}
//Remove the table row from the browser
var tableRow = document.getElementById("TODO-WHAT ID");
if (row != null)
{
//TODO: how to delete the tableRow from the DOM tree?
//document.Delete(tableRow) ?
}
//return false to prevent a postback
return false;
}
//]]>
</script>
What combination of ASP code can be used to create the above? i hear that asp:LinkButton has an OnClientClick event, where you can wire up a javascript function:
<asp:LinkButton ID="linkDelete" runat="server"
Text="Delete"
OnClientClick="DeleteItem(<%# GetDeleteUrl((ActionItem)Container.DataItem) %>);"/>
Problem is that the rendered HTML is literally containing:
<a onclick="DeleteItem(<%# GetDeleteUrl((ActionItem)Container.DataItem)) %>);" ...>
Delete
</a>
If i change the client click event handler to:
OnClientClick="DeleteItem('todo - figure this out');"/>
it works - as well as "todo - figure this out" can work.
Preventing Postbacks
The dummied down above javascript call actually happens (i can see my alert), but there's the next problem: Returning false from the javascript function doesn't prevent a postback. In fact, i can see that the href on the generated html code isn't "#", but rather
javascript:__doPostBack('ctl0....
i tried changing the ASPX code to include the OnClick handler myself:
OnClick="#"
OnClientClick="DeleteItem('todo - figure this out');"
But the compiler thinks the pound side is a pragma, and whines:
Preprocessor directives must appear as
the first non-whitespace character on
a line
Table Row Identity
The table rows don't have an ID, they're generated by the asp:repeater.
How can the javascript function know what triggered the click event? The javascript needs to be able to find the element, and remove it from the tree.
Note: i would of course prefer fade+collapse animation.
Normally you get an element by using
var tr = document.getElementById("the table row's id");
But the table rows don't have an easily knowable ID. Since there are multiple rows, the server generates the ID as it builds the table. i realize some solution is going to have to involve changing:
<TR>
into
<TR runat="server">
so that there will be server generated identity for each table row, but how do i reference the generated name from javsscript?
Normally i would have thought that the scripting problem would be solved by using multiple paramters:
function DeleteItem(tableRowElement, deleteUrl)
{
//Do a web-hit of deleteUrl to delete the item
//remove tableRowElement DOM object from the document tree
}
But the problem is just pushed elsewhere: How do you populate tableRowElement and deleteUrl for the call to the javascript function?
Such a simple problem: convert a click from a postback to client-side.
The volume of problems involved is getting quite idiotic. Which seems to indicate that either
the idea solution is something completely different
there is no solution
References
Stackoverflow: How do I fade a row out before postback?
Stackoverflow: Javascript before asp:ButtonField click
asp.net: Accessing repeater elements from javascript.
Stackoverflow: How to access repeater generated elements?
jQuery can dig out the tags for you:
$("[id$=linkDelete]").click(function() {
DeleteItem(this.href);
});
That code says "find all the DOM elements whose ID ends with 'linkDelete' and wire up the following click event handler".
I would recommend against implementing the Delete function through links in this way. Delete links are a security risk.
Rather, it's better to require a post to that url instead. If you want to be doing ajax, I would strongly recommend using a javascript framework so you don't have to deal with the differences in how different browsers implement XmlHttpRequests.
For instance, in jQuery you could do it like this:
$.post('Delete.aspx',{itemGuid:'{19a149db-5675-4eee-835d-3d78372ca6f9}'},
function(data, textStatus) {
if (textStatus == 'success') {
$(this).parents('tr:eq(0)').fadeOut();
}
});
which would do both the ajax call and the fadeout effect you want.
You could then access the item guid in Delete.aspx from Request.Form["itemGuid"], and this wouldn't be vulnerable to link attacks.
Preventing Postbacks
The server is generating a postback wireup because you're using a server control. Use a plain <a> tag without a runat='server' directive.
Table Row Identity
I usually do this by databinding an ID column of some kind and putting this in the repeater template:
<tr id='<%#Eval("ID")%>'>
P.S. I hate to sound like a fanboy, but jQuery will make all of these things an order of magnitude easier. You should really consider it if you can. Otherwise, you're going to be in a world of hurt trying to implement these features in a consistent way across browsers.
P.P.S. If the Delete.aspx and similar urls are only going to be called from javascript, I would recommend using ashx http handlers instead. You can do all of the same server logic without the needless overhead of a full-blown page.
mine usually comes out looking like
<asp:LinkButton runat="server" OnClientClick='<%# Eval("ID", "DeleteItem(this, \"{0}\"); return false;") %>' Text="Delete" />
that will make html that looks like
<a id="blah_blah_ctl01" onclick='DeleteItem(this, "{19a149db-5675-4eee-835d-3d78372ca6f9}"); return false;'>Delete</a>
I include the "this" reference so that you can have access to the dom and delete the link...or it's parent or whatever. From there it's pretty straight forward to use jQuery to actually do the posting and DOM manipulation. The "return false;" disables the postback.
The other answerers found various bits related to different aspects of the question. i managed to cobble together a complete solution. i've copy/pasted the relavent snippits here.
The first important change is the use of an asp:LinkButton which allows as OnClientClick event, which gives you direct access to the javascript OnClick event:
<asp:repeater ID="itemsRepeater"
OnItemDataBound="itemsRepeater_ItemDataBound"
runat="Server">
<itemtemplate>
<tr>
<td>
<asp:HyperLink ID="linkView" runat="server"
Text="<%# GetItemText((Item)Container.DataItem) %>"
NavigateUrl="<%# GetViewItemUrl((Item)Container.DataItem) %>" />
</td>
<td>
<asp:LinkButton ID="linkImpregnate" runat="server"
Text="Impregnate"
OnClientClick="<%# GetImpregnateUrl((Item)Container.DataItem) %>" />
</td>
</tr>
</itemtemplate>
</asp:repeater>
The code-behind manually builds presentation code (yay for separation of controller and view!) that contains a javascript call.
protected string GetNodeAcknowledgementClientClick(Item item)
{
if (!(item is HotGirl))
return ""; //this shouldn't be called for non-acknowledgements, but i won't fail
HotGirl girl = (HotGirl)item;
String szOnClientClick =
"return ImpregnateGirl(this, "+
Toolkit.QuotedStr(girl.GirlGUID.ToString()) + ", "+
Toolkit.QuotedStr(GetItemName(item))+");";
return szOnClientClick;
}
And finally in the aspx, i find a random spot to mash in some javascript:
<script type="text/javascript" src="Javascript/jquery.js"></script>
<script type="text/javascript">
//<![CDATA[
function DeleteItem(sender, girlGuid, girlName)
{
if (!confirm("Are you sure you want to impregnate "+girlName+"?"))
{
return false;
}
$.post(
'ImpregnateGirl.aspx?GirlGUID='+nodeGuid,
function(data, textStatus) {
if (textStatus == 'success')
{
$(sender).parents('tr:eq(0)').hide();
}
else
{
return false;
}
}
);
//return false to suppress the postback
return false;
}
//]]>
</script>
i would have made the jQuery do a post, as a security measure as guy suggested, but jQuery would give an error, rather than posting. Rather than care i chose to not care.

Resources