Javascript won't work on Html server control? - asp.net

I am writing a website with ASP.Net.
I will have lots of html generic controls like <div> <span> and so on..
I have some onclick javascript functions, onmouseover javascript functions..
They are working fine..
Then I need to control them on the server side.
So, I add runat="server"..
After that, all the javascripts aren't working anymore..
I understand they aren't working coz all the events are now going back to server side.
So, is there anyway to make them work??
For eg,
<div id="myDiv1" onclick="myfunction(para1)"><img src="..." /></div>
the above code is working..
<div id="myDiv1" runat="server" onclick="myfunction(para1)"><img src="..." /></div>
the above code is not working...
I can make it work, probably by
<div id="externalDiv1" onclick="myfunction(para1)"><div id="myDiv1" runat="server" ><img src="..." /></div></div>
Is there any other way?

I assume that you used document.getElementById() to get an element by its id. If you are using master pages, the IDs of server controls will be changed after rendering to the page, in that case, you have to use its ClientID
for e.g.
var myDiv1 = document.getElementById("<%= myDiv1.ClientID %>");

Server-side or client-side controls makes no difference as far as javascript is concerned. ALL server-side controls end up being rendered as normal HTML controls. If your javascript functions are not working might be because you are accessing them by the wrong id since by making them server-side controls they can now have ids that follow a pattern like <parent_id>_<control_id>.
For example, a span element declared like this:
<span id="mylabel" runat="server"> testing</span>
may end up being rendered as:
<span id="MainContent_mylabel"> testing</span>
ASP.NET 4.0 has a feature called CliendIDMode which can be set to static, meaning, that your ids on the markup will stay unchanged after the page is rendered.

Related

How do I style an ASP.NET HTML server control by ID?

When I create an HTML server control in ASP.NET 4.5 with an ID and use CSS to style that ID, it fails. When I inspect the source of the ASPX page, it shows that ASP.NET has changed my control's ID. In this instance...
<div id="PasswordStatus" class="well well-sm" runat="server">
Current
</div>
...becomes...
<div id="article_PasswordStatus" class="well well-sm">
Current
</div>
Can I then reliably (and with best practices in mind) just create the CSS style for #article_PasswordStatus instead? Or should I create a one-use CSS class for it, something like...
<div id="PasswordStatus" class="well well-sm password-status">
Current
</div>
Preferably, can I still somehow use the original ID I assigned?
Note: I do not want to convert this to a Web server control.
Assuming .net 4 and greater, you can use ClientIDMode. Your HTML would be like this
<div id="PasswordStatus" class="well well-sm" runat="server" ClientIDMode="Static">
Current
</div>
When using Static the ClientID value is set to the value of the ID property. If the control is a naming container, the control is used as the top of the hierarchy of naming containers for any controls that it contains.
Add in the ClientIDMode="Static" option to ensure your client Ids do not change.
Information can be found here.
<div id="PasswordStatus" class="well well-sm" runat="server" ClientIDMode="Static">
Current
</div>
This option forces the control’s ClientID to use its ID value directly. No naming container naming at all is applied and you end up with clean client ids
It's usually a best practice to use classes for css styling instead of IDs. You can avoid problems like this, reuse your css and so on, so that would be the path I'd choose.
ID in asp.net (webforms) can be modified in various ways and I wouldn't rely on that personally.

Is it possible to replace an asp:button with a HTML element

I'm using asp forms and wanted to know if it's possible to replace the standard buttons with HTML elements that are styled using CSS.
My login page uses a standard button
<asp:Button ID="LoginButton" runat="server" Text="Login"
onclick="LoginButton_Click" />
linked to code behind (C#) which performs the login check.
I've seen some nice buttons implemented using the HTML <button> element and styled with CSS which can have features such as images and roll over highlighting. The basic HTML looks like this
<button type="submit" class="positive" onclick ="...">
<img src="/icons/tick.png" alt=""/>
Login
</button>
I've seen another question discussing the Difference between asp:button and html's button so I understand the <button> element is not a drop-in replacement but I'd like to know if the asp:button can be replaced and still call the LoginButton_Click C# code behind?
EDIT:
Although I'm using ASP I don't mind using some client side javascript if necessary.
The buttons I saw which got me thinking about this were found here: Rediscovering the Button Element
EDIT 2:
I tried the answer from XIII using the LinkButton asp control and that worked, rendering the button as I wanted and activating the C# when clicked
<asp:LinkButton ID="LoginBtn" CssClass="button positive"
OnClick="LoginButton_Click" runat="server">
<img src="/icons/tick.png" alt=""/>
Login
</asp:LinkButton>
Javascript is inserted in to the page (as mentioned by Curt) which was not a problem for me but may be for other people; but since the asp:loginview and other controls associated with forms authentication already need javascript I'm not sure this is a problem with the solution.
I decided to accept jwiscarson's answer as this is a cleaner implementation and, despite what I thought, <button> can be a drop-in replacement for <asp:button>
The answer to your question:
if the asp:button can be replaced and still call the LoginButton_Click C# code behind?
is yes. If you have a button like:
<button type="submit" id="submit" class="positive" runat="server">Submit</button>
The attribute you need to set is not onclick, but onserverclick. You could also do something like:
protected override OnInit(EventArgs e)
{
submit.ServerClick += new EventHandler(submit_ServerClick);
}
If you need to do styling on that button, I think the best way to tackle that is via CSS classes like you have in your example.
An alternative approach would be to make use the LinkButton control and style that completely with CSS. We used to do so for a certain project in the past. Worked out pretty great for our customer.
The property of interest if CssClass
You may set CSS class via cssClass property of <asp:Button/>. However you may set runat="server" and onserverclick="LoginButton_Click" attribute to <button/>.
You could use HTML button if you desire, and learn how to call the __doPostBack() method with the proper arguments. Asp.Net buttons and HTML buttons are pretty much the same when it comes to the way they are rendered in the client.
As had been posted here already you could style the HTML rendered by your asp:button or use another asp control. Your asp:button will be rendered as a <input type="submit"> with possibly more limited CSS options than a <button> tag.
From some googling I think it is possible to get a <button> tag rendered but it looks like a non trivial excercise see How can I use the button tag with ASP.NET?

Including Javascript with a custom control in an ASP.Net website

I have a custom date control which is essentially a text box and the ajaxToolKit calendarExtender. I want to include Javascript in the control and have it work properly no matter what page the control is on. The control is called DateControl.ascx
So I have two Javascript functions, dateEditor_OnShown and dateEditor_OnHiding. They get tied up in the page load of DateControl.ascx via...
CalendarExtender.OnClientShown = "dateEditor_OnShown";
CalendarExtender.OnClientHiding = "dateEditor_OnHiding";
The DateControl tool is used on two separate pages. If I put the straight Javascript directly into the DateControl's HTML it will work only on the default page but crashes when I load up the next page with the control. The error is a js runtime error 'dateEditor_OnHiding' is undefined.
If I try to link to the Javascript file from my DateControl's html via...
<script type="text/javascript" src="../JavaScript/IE6CalendarExtenderFix.js"></script>
... instead of having the Javascript directly in the page, it crashes immediately with the same error. I should note that the path to the js is correct.
The only way I can really get it to work is if I link to the javascript on every page that the control is used.
UPDATE: I feel the need to clarify a little bit. The solutions suggested are much appreciated, but either I am not understanding or they just will not work in my case for whatever reason (quite possibly the former).
So, this is basically what my control looks like...
<div id="CustomDateControl" style="<%# ControlStyle %>">
<div id="TextBox" style="display:inline; white-space:nowrap;">
<asp:TextBox runat="server" ID="txtCalender" Style="<%# TextBoxStyle %>" />
</div>
<div id="Calendar" runat="server">
<ajaxToolkit:CalendarExtender
runat="server"
ID="CalendarExtender"
Format="MM/dd/yyyy"
TargetControlID="txtCalender"
PopupButtonID="CalenderImage" />
</div>
</div>
In the aspx page, with that exact code, if I put the exact javascript in script tags so the page looks about like so...
<script type="text/javascript">
function dateEditor_OnShown(dateControl, emptyEventArgs) {
...
}
function dateEditor_OnHiding(dateControl, emptyEventArgs) {
...
}
</script>
<div id="CustomDateControl" style="<%# ControlStyle %>">
<div id="TextBox" style="display:inline; white-space:nowrap;">
<asp:TextBox runat="server" ID="txtCalender" Style="<%# TextBoxStyle %>" />
</div>
<div id="Calendar" runat="server">
<ajaxToolkit:CalendarExtender
runat="server"
ID="CalendarExtender"
Format="MM/dd/yyyy"
TargetControlID="txtCalender"
PopupButtonID="CalenderImage" />
</div>
</div>
This still crashes when accessing the control in the second page (not the first which is the default page) saying 'dateEditor_OnHiding' is undefined. Now, if I link to a js file with the same code using a relative path as suggested below I still get the same results.
Also, if as suggested below, I override OnPreRender and run RegisterClientScriptInclude, I once again get the same results. The control always works on the default page but never on the second page even though as far as I can tell the script is included in the control.
Any ideas?
append following code in your User Control.
protected override void OnPreRender(EventArgs e)
{
Page.ClientScript.RegisterClientScriptInclude("DateControl", this.ResolveClientUrl("~/JavaScript/IE6CalendarExtenderFix.js"));
base.OnPreRender(e);
}
Problem with control-relative file paths
You are probably having problems with relative paths to your JS file. You are specifying relative path to your custom control. You should probably write user control. Anyway. Your JS file is relative path to your custom control, but not relative to the containing page, so your JS file actually never loads. That's why your event handlers are undefined.
The easiest way would be to use absolute paths. Since you're working with user controls you can easily prepend application root folder.

Expanding ClientID in an event string

I'm having a problem with <%= obj.ClientID %> expansion, in a .ascx user control.
I have a .js file, containing a javascript function:
function doSomething(objectId)
{
...
}
I have a .ascx file, with some html elements, and in one element's onclick= I want to call doSomething(), passing the ID of an element in that .ascx file, where the passed ID is of an element other than the one being clicked on, so I can't use "this.".
Maybe it'd be clearer with an example.
This works:
<script type="text/javascript">
function redirect()
{
doSomething('<%= top.ClientID %>');
}
</script>
<div id="top" runat="server">
<img src="..." alt="..." onclick="redirect();"/>
</div>
But this does not:
<div id="top" runat="server">
<img src="..." alt="..." onclick="doSomething('<%= top.ClientID %>');"/>
</div>
When I look at the source, I see that the <%= %> substitution has not happened, instead of "doSomething('ctl00_myControl_top');" I get "doSomething('<%= top.ClientID %>');"
For some reason, the script expansion happens in the former case, but not in the latter. The work-around, of course, is not acceptable because it will break if I include multiple copies of the control on a page - only one instance's "redirect()" function will be accessible.
Any ideas on how to make this substitution work?
Works on my machine?
<div id="top" runat="server">
rarrarara
</div>
Becomes
<div id="ctl00_ContentPlaceHolder1_top">
rarrarara
</div>
Consider an alternate route:
Ensure that the control you are referencing in JavaScript using the inline expression <%= (controlName).ClientID %> has its 'ClientIDMode' specifier set to a static value and then simply use the text in the ID field of that control to refer to it. I ended up using this in a recent project it works great. Please see the link below for a more detailed explanation:
Code Project - ASP.NET v4.0 Client ID Feature
Along with setting the 'ClientIDMode' specifier to "Static", I found a useful idea regarding placing text from a global resource file (in the case of language switching) into a field of a standard HTML control that does not have to run at the server level. I used this on a standard HTML button that was supposed to call a JavaScript function that would show/hide a specific div or ASP Panel. Use the GlobalResource function in the inline expression tags like so:
<input id="btnToggleFilterOptions" type="button" value="<%=GetGlobalResourceObject("SiteResource", "btnToggleFilterOption")%>" onclick="javascript:ToggleCssClass('divFilterOption','visible'); return false;" class="button submit" />
<asp:Panel ID="divFilterOption" ClientIDMode="Static" runat="server">
<asp:TextBox ID="txtFilterOption1" runat="server" />
</asp:Panel>
I know this is an old post, but it is a popular hit when searching on Google for Asp .NET and ClientID. I hope this helps somebody else out!

How to control usercontrol from javascript

I have an usercontrol with an attribute targetUrl. I add this user control to a page and write targetUrl attribute from this page like below:
<PBG:Modal ID="Modal1"
runat="server"
Height="180"
Width="500"
src="pop_adres_giris.aspx"/>
This worked properly, but I want to change the targetUrl attribute from javascript. And I can't do it. I write code like below, but it didn't work.
var frm = document.getElementById('Modal1');
frm.targetUrl = 'pop_adres_giris.aspx';
How can I do it?
The UserControl object, which generates HTML on the client side, are not accessible as the rich objects which are available when handling server side calls.
Depending what the UserControl is, you will need to use a different method to get it and set the "targetUrl".
In addition, to ease your accessing of elements within the DOM you may want to consider using a library such as jQuery or prototype
Once you have declared your control, for instance, if you were using an asp:Hyperlink control:
<div id="hyperlink_holder">
<asp:Hyperlink ... NavigateUrl="http://someurl" />
</div>
You know that asp:Hyperlink generates html like <a href="http://someurl" ... />
So we can access the element and change the link like:
$('#hyperlink_holder a').attr("href", "http://newurl");
In addition, note that the ID you give an item in ASP.NET is not necessarily the ID which will render in the id element in the HTML; it is instead a concatenation of a number of ids; therefore use selectors based on non runat="server" controls where possible, or pass the ClientID of the UserControl through to the client to use for selection if absolutely necessary.

Resources