Tales from the Evil Empire

Bertrand Le Roy's blog

News


Bertrand Le Roy


Add to Technorati Favorites Tales from the Evil Empire - Blogged

Blogs I read

My other stuff

Archives

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

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