If/else logic within a table cell using ASP - asp.net

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

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);

How do I pass parameters in window.open method

How do I pass parameters in window.open method.
<table id="tblUsers" cellspacing="0" >
<asp:Repeater ID="repUsers" runat="server">
<ItemTemplate>
<tr><td> <a ID="hlUser" runat="server" Target="_new" onclick="return OpenWindow();" ><%# Eval("Username") %></a></td></tr>
</ItemTemplate>
</asp:Repeater>
</table>
function OpenWindow() {
var toUsername = document.getElementById("hlUser");
window.open("ChatWindow.aspx?username=" + toUsername.value, "ChatWindow", "width=350,height=250");
return null;
}
I don't know much about asp.net, but looks like you have a javascript problem. Isn't document.getElementById("hlUser") an <a> element? It has no value attribute.
If you want to get the text element inside the <a> you could query the text property, or innerHTML.
<a id="hlUser">somevalue</a>
document.getElementById('hlUser').text will return somevalue
UPDATE:
Having that <a> inside a repeater makes it impossible to know with confidence any id attribute inside it beforehand. I'd reccomend passing the <a> element, or this.text itself , or even the value using the same server-side script to the function.
UPDATE 2: I see this question might be a duplicate of How do I pass a variable using window.open()?
Just change the & to a +:
function OpenWindow() {
var toUsername = document.getElementById("hlUser");
window.open("ChatWindow.aspx?username=" + toUsername.value, "ChatWindow", "width=350,height=250");
return null;
}
At this level of code, you're working in Javascript rather than VB, and VB's use of & for concatenation is an oddity among programming languages.

Hiding the Null Fields

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.

jQuery help - find span in current table cell and adjacent cell

I have an HTML table on my form. Column 1 contains a dropdown and a hidden span, Column 2 contains a hidden span. I need to show both spans and hide the drop down after a user makes a selection. I have done something similiar in other apps using code like this
var ddl_change = function() {
var ddl = this;
$("lbl1").text(ddl.options[ddl.selectedIndex].text).show();
$(ddl).hide();
}
if have 4 dropdowns (rows in the table). For code reuse I would like to use the same handler. I suppose I could write 4 seperate handlers, but that seems like a waste.
The html for a row looks like this
<tr>
<td>
<asp:DropDownList runat="server" ID="ddlbc1" />
<asp:Label runat="server" ID="lbl1" />
</td>
<td>
<asp:Label runat="server" ID="bd1" />
</td>
</tr>
I have the full client controls Id's if I need them. Anyways, is there a way within this single function to handle any row? I added client change event handlers to all the necessary drop downs and pointed them to this single function. I verified they are all correctly wired up. I want lbl1 textx to be the ddl selectedValue, and bd1, in the adjacent cell, to have ddl selectedText. Any help from the jQuery guru's would be appreciated. Thanks guys!
Cheers,
~ck in San Diego
$("td select").change(function(e){
$(this).hide().parent().parent().find("span").show();
});
Give it a whirl. You could also manage it by directly modifying the CSS, or changing the class.
You could target the entire table at once rather than a row using $("#table-id-name select") instead of the $("td select") (which will select all TD's in the entire page).
If you gave your lists/spans classes that would help to identify them, but it could be done otherwise.
$('table select').change( function() {
var $this = $(this);
$this.hide();
var lbl = $this.next('span');
var bd = $this.closest('td').next('td').find('span');
lbl.text( $this.val() ).show();
bd.text( $this.find('option:selected').text() ).show();
});

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