This is one issue that almost all developers of ExtJs/Ext.NET applications face, maintaining client-side references for the Javascript components. The seriousness of the managing the issue effectively manifests manifold, when working on large applications in modular fashion with multiple developers involved, and components being instantized or being loaded from the server on demand.

If you are developing in pure ExtJs, you have 3 options to be able to get a reference to a Component after it has been instantized (and you have not maintained an explicit reference to it): specifying id for the component in the config options for the Component, specifying an itemId config option, or using the ref config option. However, none of these approaches is without its shortcomings.

id is almost always the least preferable option. You need to make sure manually that all items on the page whose ids are explicitly set by you are unique, which becomes quite difficult to ensure as the size and number of developers on the project increase.

itemId allows you to specify an id which is scoped locally for the container of the Component. However, if you have many deeply nested containers and components, getting your hands to a component considerably down in the hierarchy from a container listener function pretty up again becomes troublesome.

ref allows you to place a named reference to the Component along Container axis, and again requires you to navigate between container/component axis, which becomes complex as nesting increases. Moreover, the approach is unmaintainable if you later need to introduce an extra Container, which would force you to update all named ref instances placed below the new container added, as well as update javascript all over which used these named references.

Now if you are using Ext.Net/Coolite, the framework by default generates unique client-side ids for your Components, in accordance with ASP.NET’s NamingContainer rules. Again, you do not have an easy intuitive way to guess these ids on the client-side. Another option is to use the IDMode property on your Ext.NET controls. However, as soon as you use any of the Static, Explicit, or ExplicitClientID values for this enumeration property, the onus shifts on to you to ensure the uniqueness of Client Ids corresponding to the server id you set on the control.

Let me explain why all this has been big trouble for me. Since more than the couple of years I have have been developing using ExtJs/Coolite/Ext.Net, I have been involved in medium to large scale applications, with the development team geographically distributed across continents. The work is done in a modular manner using Ext.Net, developing user-controls (.ascx files) which are dynamically downloaded on demand on client depending upon user interactions. There have been hundreds of such user-controls, which might be downloaded to the client in any arbitrary fashion. I cannot rely on static Control Ids as there’s no intuitive way to ensure their uniqueness while still being able to reference them easily and logically in javascript.

Even ref and item ids are not of much use firstly because of extremely deep and nested container hierarchies (imagine a button inside a toolbar, inside a panel, inside a tab panel, inside a panel, inside a border layout, inside a window, and the need to access the button when the window is shown, and this is still a hugely simplified hierarchy).

More importantly, when the UserControl is invoked for dynamic rendering in an ajax call because of user interaction, arbitrary containers need to be injected in the control hierarchy depending upon the data from the database. This leaves any possibility of using itemId or ref defunct to be able to reference components in event listeners.

Well, that was the introduction to the problem. I will discuss how have we approached the issue and settled on a standard solution for this in a following blog post.

UPDATE: The new post with a solution to the issue is now available here – Maintaining Component References in ExtJs/Ext.Net applications – Part II.