Creating an Atlas Extender: Part One
I'm working on a production version of the app I demo'd at code camp and the need arose for me to create my own Atlas extender. Well, I could get away without using it but I want to see what these extenders are all about. So the next few posts will describe my journey through the process.
The extender I want is a ToggledPanel similar to the existing CollapsiblePanel. In the CollapsiblePanel, you specify the panel you want to collapse, the control to expand it and the control to collapse (the latter two can be the same which will create a toggle but not in the same way I want). In my slightly different ToggledPanel, you'll specify two panels and one control to toggle the two. I.E. You toggle between which panel is expanded at any given time.
One of the main drivers for this is an issue I came across with the CollapsiblePanel. In my example, I mimicked what I wanted by hooking up two existing CollapsiblePanels to the same LinkButton. This sort of gave me what I want although the animation is a little wonky.
The panel has to have its Visible property set to true in order for it to be rendered in the HTML. After that, the CollapsiblePanel uses client-side script to show or hide the panel depending on the value of the Collapsed property. If Visible is set to false, then the HTML for the panel isn't even rendered so there is nothing for the CollapsiblePanel to expand or collapse.
What it didn't give me is a way, server-side, to tell which panel is visible. Or rather, it doesn't remember if a given panel is visible or not as a result of it being expanded or collapsed. That is, the panel's Visible property is always set to whatever value it is set to initially. And for it to work with a CollapsiblePanel extender, the Visible property pretty much has to be set to true (see sidebar).
So I went about creating my own extender and as all good coders do, I started with someone else's code: namely, the existing CollapsiblePanel. I created a separate Atlas Control project to house all my at-present-non-existent extenders and mimicked the AtlasControlToolkit structure by creating a folder called ToggledPanel in it. (Incidentally, it should technically be called a ToggleablePanel but I'm not a fan of making up words.) Then I added an Atlas Control to this folder which created a bunch of files.
I'd already gone through the walkthrough so this didn't throw me too much. After that, I proceeded to copy and paste like it was going out of style. The Properties class, the Extender, the javascript file and the Designer were all blatantly lifted from the CollapsiblePanel class and I paused just long enough to change the namespace and delete the copyright notice. (I'm kidding about the copyright; call off the hounds.)
Without too much trouble, I was able to get the thing to compile and I added the necessary line to my aspx page:
<%@ Register Assembly="AtlasControlToolkit" Namespace="AtlasControlToolkit" TagPrefix="atlasToolkit" %>
so that I could use my extender in the page. Since it was an exact copy of the CollapsiblePanel, I just replaced the Atlas tags with my own and left everything else within them the same:
<suvius:ToggledPanelExtender ID="test" runat="server">
<suvius:ToggledPanelProperties TargetControlID="PanelSimpleSearch" ExpandControlID="LinkButtonPanelSwitch" CollapseControlID="LinkButtonPanelSwitch" Collapsed="False" TextLabelID="Label1" CollapsedText="Simple Search..." ExpandedText="Extended Search..." SuppressPostBack="true" />
<suvius:ToggledPanelProperties TargetControlID="PanelAdvancedSearch" ExpandControlID="LinkButtonPanelSwitch" CollapseControlID="LinkButtonPanelSwitch" Collapsed="True" TextLabelID="Label1" CollapsedText="Extended Search..." ExpandedText="Simple Search..." SuppressPostBack="true" />
< FONT>suvius:ToggledPanelExtender>
Refresh the page and voila!
As it turns out, my .js file was not set as an EmbeddedResource (and it really should have been done for me). As it also turns out, that didn't help me much as I got the same error. I double-checked the ClientScriptResourceAttribute and the Sys.TypeDescriptor.addType call in the javascript and they looked fine.
My next step was to look at the source code for the page and find where my javascript file was being loaded. It looks like the ScriptManager handles this part because I found the following in my source:
When I loaded these up in my browser, they referenced the various javascript files used by other extenders on the page. Except the second one which registered as a 404 error. Which means my script wasn't being brought into the page explaining why the behaviour wasn't registered.
The eventual solution: in a fit of Canadian-ness, I had renamed my ToggledPanelBehavior.js file to ToggledPanelBehaviour.js. I thought I saw where this file was registered and changed its name there, too but when I changed the name back, the error went away and the page began to work as its parent, the CollapsiblePanel, did.
And therein lies the issue with client-side technologies. You can make your error messages as helpful as possible but in the end, Atlas really didn't know why the type wasn't registered. There is no help at design time (in the form of Intellisense), no help at compile time and little help at runtime.
Which is not to imply that you shouldn't use Atlas. I think you should. When it makes sense (like any other tool). Like when you have a web page with so many postbacks, it looks like your site is having a seizure every time you click the page. There's some great stuff to be had with the Atlas framework. The browser compatibility layer alone is reason enough to use it. But expect an environment closer to ASP than to ASP.NET, despite the tremendous effort the Atlas team has gone through in order to hide that aspect of client-side development.
The full extender described here will be available when I'm done building it. And it might have been by now if I wasn't wasting my time talking to you people.