I tried to separate javascript from a custom search grid element from html in a .ascx file. In the first iteration, I used the jQuery (document) .onReady function to attach my initialization.
The problem is that the <% =%> tags used in jQuery selectors were not correctly interpolated and the controls that javascript worked on were not found using jQuery selectors.
Next, I tried to create a json object in the page initialization and write it using the asp.net method Page.ClientScript.RegisterClientScriptBlock. This worked fine, but with flaws: the hard-coded json object name and keys in the asp.net file and javascript file. This is disadvantageous because there are now “two truth points” to maintain and, moreover, there is the possibility of a clash of names on the final page displayed.
The most elegant solution in asp.net and using jQuery is to create ajax script behavior in javascript. Then, in asp codebehind, register the script behavior properties in the GetScriptDescriptors () method of the IScriptControl interface, adding the server server ClientID as the script descriptor property.
// Ajax Javacsript Code below: Type.registerNamespace('SearchGrid'); // Define the behavior properties // ButtonBehavior = function() { ButtonBehavior.initializeBase(this); this._lnkSearchID = null; } // Create the prototype for the behavior // // SearchGrid.ButtonBehavior.prototype = { initialize: function() { SearchGrid.ButtonBehavior.callBaseMethod(this, 'initialize'); jQuery('#' + this._lnkSearchID).click(function() { alert('We clicked!'); }); }, dispose: function() { SearchGrid.ButtonBehavior.callBaseMethod(this, 'dispose'); jQuery('#' + this._lnkSearchID).unbind(); } } // Register the class as a type that inherits from Sys.Component. SearchGrid.ButtonBehavior.registerClass('SearchGrid.ButtonBehavior', Sys.Component); if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Asp.Net code below:
public partial class SearchGrid : System.Web.UI.UserControl, IScriptControl { // Initialization protected override void OnPreRender(EventArgs e) { if (!this.DesignMode) { // Test for ScriptManager and register if it exists ScriptManager sm = ScriptManager.GetCurrent(Page); if (sm == null) throw new ApplicationException("A ScriptManager control must exist on the current page."); sm.RegisterScriptControl(this); } base.OnPreRender(e); } protected override void Render(HtmlTextWriter writer) { if (!this.DesignMode) sm.RegisterScriptDescriptors(this); base.Render(writer); } // IScriptControl Members public IEnumerable<ScriptDescriptor> GetScriptDescriptors() { ScriptBehaviorDescriptor desc = new ScriptBehaviorDescriptor("SearchGrid.ButtonBehavior", this.ClientID); desc.AddProperty("lnkSearchID", this.lnkSearch.ClientID); yield return desc; } public IEnumerable<ScriptReference> GetScriptReferences() { ScriptReference reference = new ScriptReference(); reference.Path = ResolveClientUrl("SearchGrid.ButtonBehavior.js"); return new ScriptReference[] { reference }; } }
The advantage is that you can create stand-alone reusable elements using JavaScript code contained in its separate file (or as a web resource) when transferring state and context, which otherwise could be interpolated using an angle, percent equal syntax required for jQuery to work.