views:

3122

answers:

7

How do you add Javascript file programmatically to the user control?

I want the user control to be a complete package - ie I don't want to have to add javascript that's related to the user control on the page where it's used, when I can do it inside the control itself.

Since there is no Page object in the user control, how would you do it?

A: 

I generally do it when rendering the HTML for the control and depending on whether it's a library injection or an instance injection I use the Items collection to specify whether or not I have already produced the code for a control of this type during the current request using a unique identifier.

Something to the effect of:

    protected override void Render(HtmlTextWriter writer)
 {
  base.Render(writer);

  //Check if the Object Script has already been rendered during this request.
  if (!Context.Items.Contains("xxx"))
  {
   //Specify that the Object Script has been rendered during this request.
   Context.Items.Add("xxx", string.Empty);
   //Write the script to the page via the control
   writer.Write([libraryinjection]);
  }
  //Write the script that instantiates a new instance for this control
  writer.Write([instanceinjection]);
 }
Quintin Robinson
I am assuming this is done inside the .ascx.cs file?
gnomixa
It can be done at the ascx.cs level or if the control is pure code at the code level in your library.
Quintin Robinson
oh ok, whats [libraryinjection]? pardon me, I have never seen this before:)and what do you mean by xxx? something like myscript.js?
gnomixa
yes that was just a placeholder, if you want to package your script has a resource or something to that nature that would be the string representation of it, whether it be something "<script src='myscripthandler.ashx?f=myscript.js'></script>" or the entire script itself.
Quintin Robinson
+2  A: 

You can register client script includes using the ClientScriptManager. Page is accessible through the Control.Page property.

Page.ClientScript.RegisterClientScriptInclude (
  typeof ( MyControl ), "includeme.js", "js/includeme.js"  );

EDIT: Sorry, for a total "complete package", its possible using scripts as Embedded Resources, and aquire dynamic URL's through the WebResource.axd handler. If this is not considered totally complete, then i guess it could be put in App_LocalResources, but it never gonna be just one file, unless the code and script is inline.

baretta
The user specifically mentioned he wants his entire control to be a "complete package". This solution assumes that the control is added _with_ a javascript file, which wouldn't be a complete package.
David Morton
yes, thanks David! I want to have a complete encapsulation.
gnomixa
A: 

If you have the text of the actual javascript in your .CS file, you can call Page.ClientScript.RegisterClientScriptBlock.

The following assumes that "GetScript()" returns the actual javascript you want added to the rendered control.

Page.ClientScript.RegisterClientScriptBlock(GetType(), "controlScriptName", GetScript());
David Morton
I would like to have javascript in the separate file. Is it possible to programmatically add a JS file to the user control? If not I will just use Dennis's solution
gnomixa
You could read the file to a string using something like File.ReadAllText and then use that text to register the client script block, but if you want the item in it's own file, I would suggest Dennis' solution.
David Morton
thanks! wow, didn't think that adding a js file to a user control is such a headache.By the way I have <script> </script> inside the .ascx now and it works, but because there is no <head> tag in the user control, it somehow seemed sketchy, but I think I will stick with it.
gnomixa
+1  A: 

Good question!

A UserControl should be a single package without any dependency on a JavaScript or a CSS file. You will need to make the JS and CSS files as embedded resources. Right click properties and set build action to embedded resources. Then you need to inject the JavaScript and CSS files as WebResources.

Here is one article that I wrote yesterday which talks about the same scenario:

http://highoncoding.com/Articles/502_Creating_RadioButton_Validation_Using_Custom_Validator.aspx

azamsharp
I am using a web site project rather than web application, so i don't have AssemblyInfo.cs file.I would rather keep using this model as I like it better than web application project.
gnomixa
The website project was a big mistake by Microsoft. It is slow as hell since it creates assemblies for everything! On the bright side now you can use your user controls as server controls.
azamsharp
+5  A: 

GOT IT!

In the Page_Load method of control.ascx.cs file:

        LiteralControl jsResource = new LiteralControl();
    jsResource.Text = "<script type=\"text/javascript\" src=\"js/mini-template-control.js\"></script>";
    Page.Header.Controls.Add(jsResource);

    HtmlLink stylesLink = new HtmlLink();
    stylesLink.Attributes["rel"] = "stylesheet";
    stylesLink.Attributes["type"] = "text/css";
    stylesLink.Href = "css/mini-template-control.css";
    Page.Header.Controls.Add(stylesLink);

This will load css and Javascript into the head tag of the main page, just make sure that the head has runat="server". Ditto!

gnomixa
Gnomixa, very nice solution. +1
MagicAndi
This is so cool! i used to just put all the script in the ascx design page. but how do you handle cases where the javascript file is already added to the page header (maybe by a different ascx control)
zaladane
@zaladane, i have never had to deal with this case as i control fully what is loaded and when. The way I would do it, is write a simple function that loops over what's added and makes sure that something is not added twice. But, I think that you can add the same js file several times to the same page, shouldn't affect anything at the end. Try it out and see to make sure.
gnomixa
A: 

The same as gnomixa's response, only a bit cleaner:

HtmlGenericControl js = new HtmlGenericControl("script");
js.Attributes["type"] = "text/javascript";
js.Attributes["src"] = "jscript/formfunctions.js";
Page.Header.Controls.Add(js);

from http://www.aspdotnetfaq.com/Faq/How-to-Programmatically-add-JavaScript-File-to-Asp-Net-page.aspx

Contra
A: 

Question: what will happen if output caching is set on the usercontrol?

Boris
i haven't tried it, but i don't see how it would make any difference. You might want to play with it yourself to know for sure though.
gnomixa