Tales from the Evil Empire

Bertrand Le Roy's blog

News

Ads Via DevMavens

ASP.NET AJAX UpdatePanel Control: Add Ajax interactivity to your ASP.NET 2.0 web pages


follow bleroy at http://twitter.com

Bertrand Le Roy




Add to Technorati Favorites

Blogs I read

My other stuff

Hack: using live bindings outside templates

A comment on this post is asking whether it is possible to create bindings outside of a template. The point of doing that is that you don’t necessarily want to render a template just to set-up a few bindings.

Well, bindings are really implemented by a component, Sys.Binding, and a markup extension, which instantiates that component through the convenient {binding foo} syntax.

While the markup extension is only understood by the template engine, the component can be instantiated like any other component, through $create or declaratively (thanks to Dave for pointing me to how this can be done).

Here is a sample page where two bindings are created (imperatively and declaratively) to bind a span’s text (imperatively) and an input’s value (declaratively) to the same plain JavaScript data object. Modifying the value in the input changes the data object, which in turn changes the span that is also listening to it.

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Binding</title>
    <script type="text/javascript">
        var data = { answer: 42 };

        function pageLoad() {
            $create(Sys.Binding, {
                target: $get('answerDisplay'),
                targetProperty: 'innerText',
                source: data,
                path: 'answer',
                mode: Sys.BindingMode.oneWay
            });
        }
    </script>
</head>
<body xmlns:sys="javascript:Sys"
      xmlns:binding="javascript:Sys.Binding"
      sys:activate="*">
    <form id="form1" runat="server">
    <asp:ScriptManager runat="server" ID="SM1">
        <Scripts>
            <asp:ScriptReference
                Path="~/Script/MicrosoftAjaxTemplates.js" />
        </Scripts>
    </asp:ScriptManager>
    <div>
        <span id="answerDisplay"></span><br />
        <input type="text" id="answer"
            sys:attach="binding"
            binding:target="{{ $get('answer') }}"
            binding:targetproperty="value"
            binding:source="{{ data }}"
            binding:path="answer"
            binding:mode="{{ Sys.BindingMode.twoWay }}" />
    </div>
    </form>
</body>
</html>

Not quite as convenient as being able to directly use the markup extension but it gets the job done. Please also be aware that the overhead in rendering a template is very small and the convenience of the markup extension may be preferred over this. Here is the same page using a DataView:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Binding</title>
    <script type="text/javascript">
        var data = { answer: 42 };
    </script>
</head>
<body xmlns:sys="javascript:Sys"
      xmlns:dataview="javascript:Sys.UI.DataView"
      sys:activate="*">
    <form id="form1" runat="server">
    <asp:ScriptManager runat="server" ID="SM1">
        <Scripts>
            <asp:ScriptReference
                Path="~/Script/MicrosoftAjaxTemplates.js" />
        </Scripts>
    </asp:ScriptManager>
    <div sys:attach="dataview" dataview:data="{{ data }}">
        <span id="answerDisplay">{binding answer }</span><br />
        <input type="text" id="answer" value="{binding answer}"/>
    </div>
    </form>
</body>
</html>

Comments

Drew Marsh said:

So are you guys planning on adding the support to the new engine so that the processing of the markup isn't limited to templates only? Ya know, how the "old" XMLScript used to process markup for even static content?

Would seem like a very strange decision NOT to since it would force this half JS/half markup world... or force everyone to put a dataview around their whole page to make it a template.

Curious,

Drew

# October 14, 2008 4:42 PM

Bertrand Le Roy said:

@Drew: no, that would kill perf. Putting a dataview around your whole page would be just as stupid as putting an update panel around a whole page...

# October 14, 2008 4:46 PM

Drew Marsh said:

Totally! So what's the solution for the simple scenario that I want to have an <input type=text/> in my page and an <input type=submit> and want to hook up the TextBox and Button controls to those to have some behavior? In XMLScript I would have done:

<script language="text/xml-script">

<page>

 <components>

  <textbox id="myTextBox" />

  <button id="myButton" click="doSomething" />

 </components>

</page>

</script>

Now I would expect to just be able to do:

<input type="text" sys:attach="textbox" />

<input type="submit" sys:attach="button" button:click="doSomething" />

Where "doSomething" is just a global JS method in my page that does some processing in response to the click event like grab the textbox and check to make sure it has a valid value first.

AFAIK this scenario just isn't possible anymore, so unless you're doing templating the markup extensions are completely useless, right? Therefore you're forced to write JavaScript to $create the static controls on your page.

Thanks,

Drew

P.S. Admittedly I haven't had time to tinker enough with the new bits to know for sure, so feel free to smack me and point me to a sample if it is indeed possible. ;)

# October 14, 2008 7:04 PM

Mojtaabaa said:

thanks for the article.i am digesting it! ;)

# October 15, 2008 12:43 AM

gramic said:

Using markup that way is much better then using Sys.Binding class from code. I saw that it is possible to set  sys:activate="*"  at the parent tag of the template.

Even that I thought about a way to data bind without creation of any template compilation but just parse properties.

As in your example: the DOM elements are already created and the data binding markup is in the properties too. Maybe just tracing the DOM properties and do the Data Binding will suffice and will not take the performance away.

# October 15, 2008 6:15 AM

Bertrand Le Roy said:

@gramic: just looking at all attributes on all elements will kill initial performance. The way activate works, it only has to look at one thing on each element: sys:attach. I hope this clarifies.

# October 16, 2008 1:49 AM

Bertrand Le Roy said:

@Drew: I'm certainly not going to smack you but the exact code that is in your comment will work just fine provided you write the button and textbox controls (or re-use the old ones from Futures). The sys:attach attributes will work just anywhere and once it's been parsed the rest of the tag is fully activated. It's a binding on its own that will need to be in a template.

# October 16, 2008 2:31 AM

Drew Marsh said:

Bertrand,

Yeah, a coworker gave it a shot shortly after he saw my comment and we saw that it worked. I deserve a smack for not trying it before asking. :P It's just that it's not shown anywhere in the Road Map being used that way and it's always talked about in the context of templates so I thought maybe we regressed somehow.

Anywho, glad to see it works and looking forward to new info @ the PDC next week!

Cheers,

Drew

# October 19, 2008 3:37 PM

Corey J gaudin said:

How do you 2-way bind a date to a textbox control? When I utilize this AJAX  Client Templating to bind to a textbox and add the jQuery Datepicker, it goes all nuts. Changing the Date on the textbox changes it to a string and doesnt really 2-way bind correctly. Is there some Datepicker associated with this library I can use to test so that it maps to and from the Javascript Object seamlessly?

# October 20, 2008 9:12 PM

Bertrand Le Roy said:

@Corey: I haven't tried the jQuery Datepicker but you can absolutely 2-way bind a textbox to a date. The trick is to use a convert function and a convertBack function on the binding to go from date to string and from string to date. The functions can use String.format and Date.parseLocale. We do have a date picker in the Ajax Control Toolkit: the Calendar behavior. www.asp.net/.../Calendar.aspx

# October 21, 2008 12:18 AM

Corey J gaudin said:

Bertrand,

Can you utilize that Calendar completely Client-side? I have used it Server Side, but I am using it on the latest blog post (using Client Template and MVC ASP.NET) on polymorphicview.blogspot.com/.../update-to-json-service-provider-using.html  

I am trying to bind a client side only Calendar control to that textbox that doesnt mess up the Live Template binding to it. The jQuery Datepicker breaks the Template Binding to it. I figured the Calendar Picker built into AJAX Toolkit would work, but have no idea how to utilize it completely client-side.

Any ideas?

# October 21, 2008 12:55 AM

Bertrand Le Roy said:

@Corey: yes, you can use it purely on the client-side but there is little documentation for that currently. There is a specific download for just the client files on the releases page. The scripts that you need are CommonToolkitScripts, DateTimeScripts, PopupExtender, AnimationScripts, ThreadingScripts. You'll also need the calendar css and of course the CalendarBehavior script. The behavior can be instantiated using $create.

# October 21, 2008 1:11 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)