InPlaceEditing - Implementing Script Behaviors in Atlas

As a followup to my original in-place editing Atlas sample, this post takes a deeper look at the sample by providing a step-by-step approach to writing script behaviors that work cross-browser, and some insight into the topic of component authoring atlas-style.

It has been a while since I posted the InPlaceEditing sample which features an Atlas extender control and script behavior. The goal was to show how the Atlas platform makes it really possible to build and incorporate rich Web experiences. This post will focus on building the script behavior. Rather than covering things line-by-line, I'll touch upon the key points. I'll cover the extender control in the next post.

One fundamental aspect of Atlas both in terms of the technology and in terms of practice is the approach of encapsulating logic and data into classes, or components (if you also want to make it declaratively usable). This approach makes script less ad-hoc, and makes larger apps more manageable and realistic. Atlas behaviors are script components that take this encapsulation to the next level. Essentially they are a reusable encapsulation of event handling logic to package some useful pattern or functionality that can be attached to HTML elements or script controls (another core Atlas concept). Behaviors can be used to extend a fairly compact or minimal control with additional useful semantics, without resorting to building kitchen-sink style controls (which do not scale in the DHTML/scripting world). For example, this post is all about the InPlaceEditBehavior. I could also implement a MaskedEditBehavior and attach it to the same textbox to get both masked editing, and in-place editing if that is desirable.

What does InPlaceEditBehavior enable specifically? It's a behavior that can be attached to a TextBox. When the textbox does not contain focus, it is replaced with a label containing the same text, thereby helping the form look less cluttered (esp. if editing in that textbox isn't the mainline scenario). The label itself can present a different look to indicate its active, can be clicked or tabbed into to switch it into edit mode.

Step 1: A Basic Behavior
Now, that I've covered what behaviors are, and the motivation behind them, and the specific behavior, lets get started with the implementation. To start, I am going to define a skeleton behavior class:

Type.registerNamespace('nStuff.Samples');
nStuff.Samples.InPlaceEditBehavior = function() {
    nStuff.Samples.InPlaceEditBehavior.initializeBase(this);
}
Type.registerClass('nStuff.Samples.InPlaceEditBehavior', Web.UI.Behavior);

Essentially I have defined a class called InPlaceEditBehavior in the nStuff.Samples namespace that derives from Web.UI.Behavior. And it calls the base class ctor in its own ctor.

Step 2: Add Properties
The next thing to do is make it more useful. I am going to add some properties. This behavior needs CSS class properties it uses to change the look and feel of labels as the mouse hovers.

nStuff.Samples.InPlaceEditBehavior = function() {
    ...
    var _labelCssClass;
    this.get_labelCssClass = function() {
        return _labelCssClass;
    }
    this.set_labelCssClass = function(value) {
        _labelCssClass = value;
    }
}

JavaScript doesn't have true properties, but as you can see, I have used the Atlas pattern that bears resemblance to properties in C# and managed code to define a read/write labelCssClass property. I can do the same for the other properties needed to customize this behavior's working.

Step 3: Support for XML-Script
This behavior needs to usable in a declarative manner. The declarative model makes it simpler to associate behaviors with controls and to customize them with property values. I need to do two things for this to happen: define the properties and associated metadata, and secondly register a tag that maps to my class type. The XML-script parser uses these to do its job.

nStuff.Samples.InPlaceEditBehavior = function() {
    ...
    this.getDescriptor = function() {
        var td = nStuff.Samples.InPlaceEditBehavior.callBaseMethod(this, 'getDescriptor');
        td.addProperty('labelCssClass', String);
        return td;
    }
}
...
Web.TypeDescriptor.addType('nk', 'inPlaceEdit', nStuff.Samples.InPlaceEditBehavior);

Basically, I am overriding getDescriptor method, calling the base implementation first so the type descriptor I hand out will contain information about all the properties (such as the bindings collection) that I am inheriting from Behavior and Component, and then adding the information about properties such as labelCssClass. I specify the type as well, so that the parser can appropriately create typed values from their string representation in the form of XML attributes. Secondly, I am declaring the tag name for this type to be "nk:inPlaceEdit".

As you can see, XML-script is completely metadata driven. The object model of the component describes the set of valid tags, and attributes. Note I can also describe events and methods in the type descriptor. Event information is used to associated event handlers and actions in markup. Method information is used to declaratively invoke methods in response to an event via invokeMethodAction.

Step 4: Add Core Functionality
OK, enough setup. Now, onto to some real work. Like most behaviors, this one needs to attach event handlers during initialization by overriding the initialize method. Do not listen to window onload, because that may have happened in the past by the time your behavior is initialized.

nStuff.Samples.InPlaceEditBehavior = function() {

    var _labelElement;
    var _labelMouseOverHandler;
    var _isEditing;
    ...

    this.get_isEditing = function() {
        return _isEditing;
    }

    this.initialize = function() {
        nStuff.Samples.InPlaceEditBehavior.callBaseMethod(this, 'initialize');

        var textBoxElement = this.control.element;
        _labelElement = document.createElement('SPAN');
        ...

        _labelMouseOverHandler = Function.createDelegate(this, this._onLabelMouseOver);
        _labelElement.attachEvent('onmouseout', _labelMouseOutHandler);
        ...
        
        if (Web.UI.InputControl.isInstanceOfType(this.control)) {
            _validatedHandler = Function.createDelegate(this, this._onValidated);
            this.control.validated.add(_validatedHandler);
        }
    }

    this._onLabelMouseOut = function() {
        Web.UI.Control.removeCssClass(_labelElement, _labelHoverCssClass);
    }
    this._onLabelMouseOver = function() {
        Web.UI.Control.addCssClass(_labelElement, _labelHoverCssClass);
    }

    this._onTextBoxBlur = function() {
        this.endEdit();
    }

    this._onValidated = function(sender, eventArgs) {
        if (this.control.get_isInvalid()) {
            this.beginEdit();
        }
    }

    this.beginEdit = function() {
        var textBoxElement = this.control.element;
        textBoxElement.style.display = '';
        _labelElement.style.display = 'none';

        textBoxElement.focus();

        _isEditing = true;
        this.raisePropertyChanged('isEditing');
    }

    this.endEdit = function() {
        if (_isInputControl && this.control.get_isInvalid()) {
            return;
        }

        var textBoxElement = this.control.element;
        _labelElement.innerHTML = textBoxElement.value;
        _labelElement.style.display = 'block';
        textBoxElement.style.display = 'none';

        _isEditing = false;
        this.raisePropertyChanged('isEditing');
    }
}

During initialization, the behavior creates a label and adds it to the DOM such that it covers the textbox. In addition it starts monitoring for user actions such as hovering over the label. A Behavior can not only listen to DOM events; it can also listen to events raised by the script control associated with the DOM event. If the control associated with the Behavior is an InputControl (which TextBox is), then the behavior sinks to the validated event and forces the textbox to remain visible even after the user has moved away from it if it is in an invalid state. You don't want the label to replace the TextBox in this case. In addition it also listens to the blur event on the textbox, and focus event of the label (to enable keyboard interaction and accessibility).

Notice the use of delegates, which are part of the OOP extensions to JavaScript provided by Atlas. These allow usage of "this" naturally within the event handlers. Also notice the usage of addCssClass and removeCssClass - These are some of the helper methods on Web.UI.Control to provide a more friendly interface to the underlying DHTML APIs provided by Atlas.

One other thing to notice is the isEditing property, and the change notification being raised in the beginEdit and endEdit methods. These change notifications form the basis of data-binding in Atlas. Any other component can now bind to this property, and the binding engine can now automatically move data around as required. Coupled with declarative markup, this mechanism immensely simplifies code (to contrast, think event handlers you'd have to write that move data around manually in imperative code.) When you write components, think about what are the meaningful properties and events from a binding perspective, so that page and application developers can start incorporating the declarative model.

Step 5: Add Cleanup Logic
One important piece of logic you do not want to forget about is dispose. While JavaScript itself does have GC, the combination of Script + DHTML DOM can lead to memory leaks as a result of circular references. The Atlas framework will take care of calling your dispose implementation at the right times. What you need to do is detach your event handlers from the DOM elements, thereby breaking the circular references.

this.dispose = function() {
    if (_labelElement) {
        _labelElement.detachEvent('onmouseover', _labelMouseOverHandler);
        _labelElement.detachEvent('onmouseout', _labelMouseOutHandler);
       _labelElement = null;
       _labelMouseOverHandler = null;
       _labelMouseOutHandler = null;
    }
    ...

    if (_validatedHandler) {
        this.control.validated.remove(_validatedHandler);
        _validatedHandler = null;
    }
    nStuff.Samples.InPlaceEdit.InPlaceEditBehavior.callBaseMethod(this, 'dispose');
}

That's pretty much it for a simple behavior. Using these concepts, you can build larger, more involved and interesting components.

Should I write a behavior or a control?
While I haven't talked about authoring controls, there is a lot of overlap. There is one technical difference: Only a single control can be associated with a given HTML element. However one of more behaviors can be associated. A behavior does require a control to exist, since it needs to be added into the behaviors collection to work. There is a subtle distinction between the two that will determine what is appropriate. You should write a control, when it is the answer to a question "What is this widget" - For example, the answer to this question for <input type="text" /> is a "TextBox". You should write a behavior when it describes one optional and independent functional aspect of a widget. Hence InPlaceEditBehavior is a behavior and not a derived TextBox.

What control should the behavior attach to?
This is a key design decision to make. My initial thought was to have a label, and to display a textbox as needed. However, I chose the opposite for the implementation. I thought I'd share some of the thoughts that led me to do this. Some will carry over to other behaviors.

If extended a label, I'd have to create a textbox dynamically. A textbox requires many properties to fully customize (too expensive to implement in script), while a label can be easily customized via a single CSS class. Furthermore, the Atlas model is to allow UI to be fully specified via HTML/CSS, providing full flexibility to the designer. The script should focus on the behavioral aspects of the application. This is a key difference from ASP.NET server controls that tend to abstract UI rendering and behavior into a single entity.

Atlas provides a templating mechanism, so perhaps the textbox could be specified in a template. But this is simply too complex in terms of the markup the page developer would have create for such a simple scenario. Templates are powerful, but use them judiciously (they are inherently complex).

At the same time, allowing the developer to specify both label and textbox in the UI would lead to designer issues, and implementation issues around overall layout of the page. Finally I decided it would be simplest if the TextBox pre-existed in the page somehow, and the relatively simpler label was dynamically created.

Usually the simpler design is also the better design and this became apparent as I proceeded with the implementation. With the textbox on the page, the functionality of the page is preserved in the absence of script. It also allows association of validation rules, and ensures the entered value is present in the form post-back. All of these are bits of goodness.

Posted on Saturday, 2/4/2006 @ 1:12 PM | #ASP.NET


Comments

20 comments have been posted.

Andrey Skvortsov

Posted on 2/5/2006 @ 5:45 AM
Excuse me,too much burden on developer side and mix of standard javascript/CLR emulation layer dosen't looks nice ever-if you can't replace javascript syntax/semantics completly-don't even try IMHO.As css/javascript developer I should say,most things you're trying to acomplish can be done in much easier way using pure javascript constructs.But CLR layer here only obsfucate underlaying javascript syntax/semantic which bubles up here and there anyway(remember SOA/REST dispute?;-).
Under "component" you understand type that has "TypeDescriptor"="getDescriptor function",which in turn only needed for doing reflection work in "XML-script parser"=imperative duplicate description of already declared javascript constructs.It looks(and behaves) ugly,don't you think?
Why,why you leave "promised" "dhtml behavior's" land-best AOP implementation I've ever seen?I understand-compatibility/standard compliance and all things like that...BUT it dosen't change the fact that all this staff looks terrible compared to simple IE behaviors-available from 5.5,I must add.
I thought you're trying to bring something new but it seems you about to replace things already work,with something looks strange in javascript land,to say least-that's slightly different,and I don't like it very much.LINQ can't replace SQL/XPath because both are DSL but LINQ is layer of abstraction useful only in "edge" cases where those meet;-)

Thanks,nice article,I'll be waiting for more.

Nikhil Kothari

Posted on 2/5/2006 @ 6:34 AM
Andrey a few points:
1. My goal is eventually information in TypeDescriptor can be derived with the addition of metadata constructs - so you won't need to imperatively define it.

2. IE behaviors are not an option because cross-browser support is super critical, so the platform can be used to write real-world apps beyond experiments. However there are some ideas in the IE behavior implementation that are interesting - we've looked at that, and will be providing support for similar concepts in a future release. I'll discuss them as things become more concrete, as well as become available, so that folks can actually start playing with them.

3. I think these layers of abstraction are important to enable encapsulation. Sure you could do it in raw JavaScript in the page (like its been done for ages), but then you'd have lots of unmanageable, non-reusable script. The OOP approach makes JavaScript more manageable, maintainable, etc. All of these things are needed the moment you want to write more complex applications, which is the new trend. New scenarios require new methodologies to help scale and meet requirements.

4. There is definitely a CLR flavor to the OOP and API extensions Atlas provides. We believe this will bring familiarity to a large number of developers from the .NET world. However, I tend to think these are fairly general concepts - properties, events, methods, metadata - are applicable to any modern programming language and environment and even the script developer will be able to pick up, and hopefully appreciate. The fact that some of them have to be simulated in JavaScript hints at the problems associated with the platform that Atlas seeks to remedy. Hopefully long-term the language matures, and that matured form becomes ubiquitous so that people can depend on it when writing applications!

One closing thought: Keep in mind is that Atlas is still in pretty early stages, and we are in fact starting from zero (raw DHTML, and raw script). Things like TypeDescriptor are low-level plumbing (agreed). The reality is you need to get the foundation right before building higher level concepts and tools that simplify overall development. In time they will also emerge.

Andrey Skvortsov

Posted on 2/5/2006 @ 8:08 AM
<quote>
3. I think these layers of abstraction are important to enable encapsulation. Sure you could do it in raw JavaScript in the page (like its been done for ages), but then you'd have lots of unmanageable, non-reusable script.
</quote>
Who say this to you?You must add also that javascript is not OO language if it's not looks like c# or something(how about JScript.NET?).It's not like c# but that dosen't means I can't express same constructs events/namespaces etc.Big question is-why you need all those constructs?You think that it's make developer's life easier but I believe that it's additional mess,if you know javascript of course-you can't give me more than pure javascript.If you don't and believe in CLR,you must look at Avalon's XAML which will replace browser eventually anyway.It seems to me you're trying to seat on both chairs,and if you failed with behavior's standartization.You think there's ability to lock down users to another CLR compatible microsoft's implementation of behaviors,but compatible with main rival,implementing IE's compatibility layer?!?Behaviors is cornerstone of framework,isn't it?;-)
I understand,you want to bring some kind of BCL into the browser-you sure that all this infrastructure is absolutly necessary?You believe that BCL in browser brings so much value by itself that can dispose value of XMLHttpRequest and javascript as whole?
If something not in use for a long time it dosen't means something wrong with it,in some cases it just waiting.

<quote>
4. There is definitely a CLR flavor to the OOP and API extensions Atlas provides. We believe this will bring familiarity to a large number of developers from the .NET world...
</quote>
You want winforms developers to build applications for browser?I don't think that's good idea...

<quote>
Keep in mind is that Atlas is still in pretty early stages, and we are in fact starting from zero (raw DHTML, and raw script). Things like TypeDescriptor are low-level plumbing (agreed).
</quote>
DHTML, and "raw" script=zero?That depends from what direction you look at this;-)
If "low level plumbing" is required for any "serious" development it must be thought-out beforehand I suppose,and be as clean as possible from begining.Tools dosen't not help here if foundation is cumbersome and ugly,I believe-not so much you can mask with tools.

Best wishes.

Nikhil Kothari

Posted on 2/5/2006 @ 1:13 PM
XMLHttpRequest or JavaScript - Atlas builds on them, not replace them. In addition, Atlas strives to be an end-to-end framework for rich Web applications. You can work on top of lower layers directly if you're more comfortable and choose to ignore the entire component framework. See my architecture (http://www.nikhilk.net/AtlasArchitecture.aspx) and programming model (http://www.nikhilk.net/AtlasProgModel.aspx) posts. We're trying to cater to multiple scenarios, requirements and personas.

I fully agree that tools help little in masking underlying issues. However, there is more thinking and vision on the team than what you see in the bits and the underlying framework is itself in development, and will require time to fully mature. Seeing the framework built from ground up alongside end-features is a natural side-effect of increased transparency and public technology previews.

I just wanted to clarify the above two points, and now rather than extending this debate, it would probably be much more constructive if you could articulate what would you want from Atlas if XMLHttpRequest and JavaScript as-is are good enough? What would you have in your ideal? I'd love to hear... constructive feedback helps improve things. Thanks!

Andrey Skvortsov

Posted on 2/5/2006 @ 1:41 PM
I mostly listener-more you speak,more response you'll get.I only can "guess",as you noted.But I'll try to summarize my vision,tomorrow...Time to sleep;-)
Thanks,for you hard work,I really appreciate you attention.

Andrey Skvortsov

Posted on 2/6/2006 @ 5:10 AM
What you think about:
http://www.c-sharpcorner.com/UploadFile/desaijm/AJAXRepeaterControl01302006213655PM/AJAXRepeaterControl.aspx
http://script.aculo.us/,discussed on http://weblogs.asp.net/bleroy/archive/2006/02/02/437203.aspx
http://bennolan.com/behaviour/
Why is it worse/better that Atlas in despite of asp.net support/CLR orientation?You argues Atlas provides better structured approach,but what if former cover 70% of use cases in much easier way?XML script is nice mixture of features similar frameworks -agree,but to be really useful you force developers to provide awkward approximation,which in turn dosen't look very nice by now.

So,what you think?

Steve

Posted on 2/6/2006 @ 5:37 AM
I'd like Atlas to help resolve some issues I currently have writting script in my asp.net pages. Note: all my current examples are not about 'ajax' but about more refine of using javascript with asp.net.

1. wiring up attributes to server side controls. I tend to have to do a attribute add on page load passing client id's in because I abhor writing javascript in my html page - instead I have .js includes. But with this model, the client id is dynamically generated which makes it difficult to use js like 'getElementById'

2. ability to create validators that accept parameters for the same reason as #1. I have a customvalidator but it only gives a place to specifiy a client function with no parameters. In my case I am validating that a user selects an item in a radiobutton list before entering text in a textbox. This validator needs to confirm the state of several controls working together, not just one control.

3. Build on the register array - the ability to have data go 2-ways - ie. if I register an array in my code behind, and the javascript then alters that array, I would like to see the server side pick up those changes (somehow). Same goes for client side changes made that the server side post needs to pickup. ie. if I add items to a listbox in client side, then hit save on a serverside post, I've always had to construct some hidden field to write the values too - which seems to be a hack in my opinion.

These are small example I know, but the ability to have tighter integration with the client/server with the same flexibility is something I'd like to see. Personally I'd rather just write server-side or "client-side" C# and not use javascript at all :)

Marc Brooks

Posted on 2/6/2006 @ 2:41 PM
Another reason to start with a TextBox is that EVERY web page should degrade properly in the absence of JavaScript to be 508 accessible. I usually start with a page that does everything through explicit post-backs and slowly replace the post-backs with behaviors. In fact, thus far I'm using Prototype and Behavior and still don't see much gain in switching to Atlas yet (though I have an open mind about it) on the client side. The server side is another story, of course!

What I would LOVE is for Atlas to take the approach that Behavior has and use CSS3 selectors to drive what behavior is attached. This would eliminate all the intrusion of JavaScript into the markup, which makes me happy.

Oh, how does the hiding and showing of the underlying input tags affect tabbing between controls?

Nikhil Kothari

Posted on 2/6/2006 @ 6:40 PM
One of these days, I need to write a sample for showing behavior binding using CSS selectors ... on my list. It is very much possible, and hopefully it'll be part of the out-of-box set of scenarios.

I think the browser does not tab into textboxes that are not visible - they are out of the tab order. Note you can't disable them from the perspective of getting the right behavior, because that would interfere with form postback.

Steve

Posted on 2/7/2006 @ 9:44 AM
Nikhil, please help with this issue:

When I have a control on a page that is within a contentplaceholder the clientid is generated automatically, ie.
ctl00$ContentPlaceHolder1$txtName

TextBox txtName = PreviousPage.FindControl("txtName") as TextBox;
TextBox txtName2 = PreviousPage.FindControl("ctl00$ContentPlaceHolder1$txtName") as TextBox;

So, as a control developer, how would I make a call to 'getElementById' if this automatic generation is taking place?

I would not want to use ctl00$ContentPlaceHolder1$txtName because this could change if someone adds another control to a page.

What is the workaround here?

Steve

Posted on 2/7/2006 @ 10:00 AM
I ended up doing this:

ContentPlaceHolder cph = PreviousPage.Master.FindControl("ContentPlaceHolder1") as ContentPlaceHolder;
TextBox tb = cph.FindControl("txtName") as TextBox;

Nikhil Kothari

Posted on 2/7/2006 @ 4:55 PM
I don't think this comment is strictly on topic of the post, but I'll go ahead and answer anyway:

In your ContentPage, you create a property of type TextBox:
public TextBox SomeTextBox {
get { return txtName; }
}
In your other page, you write PreviousPage.SomeTextBox. (You use the <%@ PreviousPage %> directive to get strong typing, so you can use the SomeTextBox property). This allows you to change the ID of the textbox, and not affect other pages. Better yet, you create a property of type string on the page, and the property getter returns the Text of the TextBox rather than the TextBox itself. This enables you to change the type of control as well, without affecting other pages.

You use the ClientID property instead of using document.getElementById with a fixed ID. For example, if I want to set up some script object, I'd do render this:
"foo.setup(document.getElementById(" + control.ClientID + "));"
and then package up the implementation of foo.setup in some script include that takes an element instance, and not string ID. See the script generated by WebParts for an example. As a result, we have no issues in our implementation resulting from ID generation on the server.

Basically things are simple, if one does not try to flow upstream against the framework, and instead use the tools and mechanism offered by the framework. Most people I've seen complaining against generated IDs are those who simply choose to ignore APIs and want to work at the level of strings.

Steve

Posted on 2/8/2006 @ 4:51 AM
"You use the ClientID property instead of using document.getElementById with a fixed ID. For example, if I want to set up some script object, I'd do render this:
"foo.setup(document.getElementById(" + control.ClientID + "));"
and then package up the implementation of foo.setup in some script include that takes an element instance, and not string ID. See the script generated by WebParts for an example. As a result, we have no issues in our implementation resulting from ID generation on the server."

This is really the heart of the matter - thank you. I don't think I've this explained too much in anything I've read - which is why I find working with server-side to client-side difficult. I know this is off topic, but I'm curious to see how this will work with Atlas.

It seems in many of these posts you make you are really deep inside the way .net works under the covers and it doesn't always come as quickly to everyone (at least me) that is trying to understand these mechanisms.

ie. if when using Atlas if I want to dynamically construct a form based on use input (let's say add additional textboxes on the form), I've used javascript - but I would always need to save the values entered into hidden fields, etc... When using Atlas I'd like this same flexibility to dynamically add elements without needing to goto javascript but rather use Atlas and access the controls by their id's rather than by storing the values in hidden fields. I used script callbacks to do some of this work back in 1.1 and I see the same ability in 2.0, I just found it awkward to use - since I wasn't really looking for callbacks, but rather was looking for ways to integrate my server-side C# functions with some client-side functionality. I would use this on items such as dropdownlists, listboxes, etc... where the enabling of a postback to get a selected value caused page postbacks which I was trying to avoid.

If this is off topic - please remove. I'm trying to see how common tasks that server-side code is either 'messy' or requires the injection of javascript - will Atlas provide solutions to a page developer. I was able to do alot with the update panels and drag & drop - this made things hopeful, now I want to see what is next in the pipeline :)

Thanks for the sample and explanations, I will dig deeper into to try to get a better understanding of how I can utilize it in my examples.

Patrick

Posted on 2/8/2006 @ 7:17 AM
Hey Nikhil, thanks for the behaviors example. Any plans for an example on writing an Atlas control?

Also would like to comment on the auto-complete behavior in Atlas. Currently it is designed so that can retrieve an array of strings from a web service. But in most database applications we use surrogate keys, so rather than just returning text, I would want the primary key returned as well (an integer), unless I am missing something?

Michael

Posted on 2/16/2006 @ 8:00 AM
Is there any method to post complete <form > data to a webservice or .aspx file using atlas. i.e asynchronous post back.

Inventisity

Posted on 3/10/2006 @ 7:02 AM
Hi Nikhil,

I am working with the January version of atlas. I have the InPlaceEdit.js setup and in my declarative xml script I have:

<label targetElement="testLabel">
<behaviors>
<clickBehavior click="test">
</clickBehavior>
<nk:inPlaceEdit labelCssClass="inPlaceEditLabel" labelHoverCssClass="inPlaceEditLabelHover" />
</behaviors>
</label>

This is giving me a JS error.

Line 1554 Object Required.

Any clues?

Thanks.

Bobby

Posted on 3/12/2006 @ 7:33 PM
"Basically things are simple, if one does not try to flow upstream against the framework, and instead use the tools and mechanism offered by the framework. Most people I've seen complaining against generated IDs are those who simply choose to ignore APIs and want to work at the level of strings. "

Where is the good starter documentation for all this? I think Microsoft and your team is moving ahead so quickly that they assume all the developers are just picking this up with no problem.

There is a real lack of documentation on this information - most books for example want to continually teach novice 'how to bind a gridview' and none of the ways in which to solve REAL BUSINESS PROBLEMS.

I'm actually a bit fed up with this elists attitude - more work needs to go into the basics - we have this Altas framework with practically no documentation and meanwhile the lead developer of the team is telling the public that they "simply choose to ignore APIs ".

Sorry - but I've searched high and low, and this information is cryptic at best, don't get me wrong, I myself will be persistent with learning it - but it's constantly 1 step forward and 5 steps back with this stuff.

Steve

Posted on 3/12/2006 @ 7:55 PM
Actually Bobby the information was available - ie. I later went and read this article:
http://msdn2.microsoft.com/en-us/library/ms178139.aspx

It describes what Nikhil was explaining to me.

ok -back on topic - Nikhil - there is one thing Bobby mentions I'd like to find more about:

ie. Let's say I want to use the Extender to create a Atlas Listbox with scrollbars - similiar maybe to the way the current Menu controls works - but rather than a url link, instead you select the item - basically a better UI than the dropdownlist with no need to autopostback.

It would be fantastic to start really simple and explain how I would do this in Atlas :)

Thanks!

Can

Posted on 3/19/2006 @ 11:24 AM
Your blog is extremely helpful. I am looking forward to see more atlas related samples.
Thank you very much.

Mohamed Irsath

Posted on 3/30/2006 @ 1:19 AM
hello, i attend your road show. Now i m developing a web project. I finished binding the data and paging.
My Question is.
Is there any possibilities to bind records with out postback during i next,previous, first or last button is clicked..


I am newer to .NET tech. i m waiting for ur reply.
The discussion on this post has been closed. Please use my contact form to provide comments.