views:

40

answers:

5

We have created a User Control for ASP.Net. At any one time, a user's profile page could contain between one and infinity of these controls. The Control.ascx file contains quite a bit of javascript. When the control is rendered by .Net to HTML, you notice that it prints the javascript for each control.

This was expected. I'd like to reduce the amount of HTML output by the server to increase page load times. Normally, you could just move the javascript to an external file and then you only need one extra HTTP request which will serve for all controls.

But what about instances in the javascript where we have something like

document.getElementById('<%= txtTextBox.ClientID %>');
How would the javascript know which user control work with? Has anyone done something like this, or is the solution staring me in the face?

A: 

Why not register the client id's you want for the controls from the server code into the client side?

ScriptManager.RegisterClientScriptBlock(string.Format("var txtTextBoxId = {0};", txtTextBox.ClientID);

Then in your javascript you can use the variable dynamically for whatever control is being rendered.

The only problem might be the naming of the variable (ie txtTextBoxId), as i dont know how you've setup your solution, hard to say - but you might need a specific naming convention for the variable names to stop duplication from happening. Maybe an indexed array?

And of course with this method, you can move your javascript into an external file.

RPM1984
This would fail for multiple controls as well, actually it'll fail quicker. Your answer would print out `var txtTextBoxId = txtTextBox; var txtTextBoxId = txtTextBox;` (which needs to be put in quotes). This would just be overriden with the last declaration of the variable, so it doesn't solve the problem at all.
Nick Craver
Sorry - forgot the quote:ScriptManager.RegisterClientScriptBlock(string.Format("var txtTextBoxId = '{0}';", txtTextBox.ClientID);And yes you're right, it would get overriden, which is why i made the comment that he might need a naming convention - such as prefixing the variable name with the id of the user control for example.
RPM1984
+2  A: 

Write functions that take IDs, put them in mysite.js and reference the file like this:

<script type="text/javascript" src="/mysite.js"></script>

Then when you make your calls in your controls do it like this:

<div onClick="DoMyFunctionThatIWant('<%= txtTextBox.ClientID %>')">...</div>

Then your function in js is something like this:

function DoMyFunctionThatIWant(domId)
{
   var obj = document.getElementById(domId);
}
Aren
A: 

Do you have the ability to use jQuery? The css selector functionality is extremely powerful for these types of scenarios. For example:

<div class="action" id="1">Node 1</div>
<div class="action" id="2">Node 2</div>
<div class="action" id="3">Node 3</div>
<div class="action" id="4">Node 4</div>
<div class="action" id="5">Node 5</div>

Then, you would have one JavaScript function and bind it to each element that meets the selector criteria. It might look like:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&gt;&lt;/script&gt;
<script type="text/javascript">
    $('.action').click(function() {
        var $t = $(this);       //---here is your contextual node
        alert($t.attr('id'));   //---this alerts the id value of your node
    });
</script>
jkody21
A: 

Here was the solution:

  • Create the external javascript file and copy all code over to it.
  • For each element in the usercontrol that needs to be referenced by the javascript, create a new Object.
  • Back in the usercontrol's ascx file, take each usercontrol's id and make it a member of the Object and make this member's value equal the id of the element in the usercontrol to which the Object refers. Do this onload.
  • Now, in each function, find the actual element you want by getting this ID out of the Object, using your control's ID as a key.

My actual full-on solution was a little different. Each usercontrol contained a telerik radgrid. The client-side event handlers for the radgrid are of the form

radGrid_eventOccurred(sender, args) {
where sender is the grid object.

So instead of using the usercontrols ID as the key in my code, I used the grid.

Say I need to update a textbox inside the usercontrol whenever I click on a row in the grid. I can now do something like this:

function radGrid_rowClick(sender, args) {
    var text = /*Get the text of the clicked row*/;

    var textBox = textBoxesObject[sender];
    textBox.set_value(text);
}
Duracell
A: 

Write a microsoft ajax client component.

This requires a lot of things to be done:

  • Write a component class in an JavaScript file.
  • Register this script file by implementing IScriptControl on the code behind class.
  • Create a instance of the client component by implementing GetScriptDescriptors for the code behind class.
  • Take the clientIDs as parameters into the descriptor, so the client component class (written in js) knows the client ids.

The component class may do all what you want because it knows all clientIds of your user control. This works for multiple instances of the same user control anyway. As a pitfall this is somewhat cumbersome to implement. But it is very clean.

Martin Kirsch