Templates and pseudo-columns

We’ve already seen that templates let us use pseudo-columns for accessing specific context information. In this post, we’ll be talking about a related subject: including code in a template through the use of sys: attributes. Currently, you’ve got the following options:

  • sys:codebefore: executes the specified JavaScript expression before rendering each element;
  • sys:codeafter: executes the specified JavaScript expression after generating each element;
  • sys:if: generates the HTML of the current element if the associated condition is true.

From the three, I think that sys:if will be the most used one. So lets start with it, shall we?

<head runat="server">
    <style type="text/css">
        .sys-template{
            display: none;
        }
        .selected{
            background-color: Gray;
        }
    </style>
    <script src="Scripts/MicrosoftAjax/start.debug.js" type="text/javascript"></script>
      <script type="text/javascript">
          Sys.require([Sys.components.dataView]);
          var data = [
            { name: "luis", address: "funchal" },
            { name: "paulo", address: "lisbon" },
            { name: "rita", address: "oporto" }
        ];
    </script>
</head>
<body xmlns:sys="javascript:Sys"
      xmlns:dv="javascript:Sys.UI.DataView">
    <div id="list"
         class="sys-template"
         sys:attach="dv"
         dv:data="{{data}}">
        <div>{{name}}-{{address}}</div>
        <hr sys:if="{{ ($index + 1) % 2 == 0 }}" />
    </div>
</body>

The previous code will show a separator line (notice the <hr>) after rendering each two items (notice that we must adapt the $index pseudo-column since it’s zero based). As you can see, the only thing it does is to decide if the current HTML element where it’s applied should be rendered or not. And that’s it…really!

The sys:codefebore and sys:codeafter might seem a little weird…the truth is that you think of them as being the equivalent of the <% %> pair you already know so well from ASP.NET :,,).

Here’s a quick example (which can be improved by using nested templates, but we’ll leave that for a future posts – for now, concentrate only on the use of the sys:codebefore and sys:codeafter attributes!):

<head runat="server">
    <style type="text/css">
        .sys-template{
            display: none;
        }
        .selected{
            background-color: Gray;
        }
    </style>
    <script src="Scripts/MicrosoftAjax/start.debug.js" type="text/javascript"></script>
      <script type="text/javascript">
          Sys.require([Sys.components.dataView]);
          var data = [
            { name: "luis", contacts: ["123123123","222222222"] },
            { name: "paulo", contacts: ["123123123", "333333333"] },
            { name: "rita", contacts: ["555555555"] }
        ];

    </script>
</head>
<body xmlns:sys="javascript:Sys"
      xmlns:dv="javascript:Sys.UI.DataView">
    <div id="list"
         class="sys-template"
         sys:attach="dv"
         dv:data="{{data}}">
        <div>
            {{name}}<br />
            <p
                sys:codebefore="for(var pos in contacts){"
                sys:codeafter="}">
                {{contacts[pos]}}
            </p>
        </div>
        <hr sys:if="{{ ($index + 1) % 2 == 0 }}" />
    </div>
</body>

We’ve changed the objects used for feeding the DataView control: now each object has a name and a collection of contacts. We’re interesting in showing the contacts (one per line) of each of the objects. If you’re using ASP.NET MVC and the web forms view engine, then you’d probably use a for sprinkled with HTML code in it…probably something like this:

<% for( var t in obj.Contacts ){%>
    <p><%= t %></p>
<% }%>

Not pretty, but that’s what most people end up doing in ASP.NET MVC 1.0 (again, when using the web forms view engine). As you can see, we start with putting the for condition on one line and are forced to close the open brace in another line. And that’s  precisely what’s going on with the previous JavaScript sample:

<p
    sys:codebefore="for(var pos in contacts){"
    sys:codeafter="}">
    {{contacts[pos]}}
</p>

Since contacts is an array, pos will return the current index which we can reuse for getting the current item from the contacts array. I think that comparing this code with the previous ASP.NET <% %> example is the best way to understand this feature. I guess you won’t be using it much, but if, by any chance, you feel that you need something like that, you can use the sys:codebefore and sys:codeafter attributes.

And I guess that’s it. Keep tuned for more in MS AJAX.

Advertisements

~ by Luis Abreu on October 19, 2009.

3 Responses to “Templates and pseudo-columns”

  1. You may have addressed this already. Sorry if you did.

    It goes back to dynamically loading html code from a secondary file. User clicks on button. And that request requires a different dv to be displayed, it could be using a different fetch query.

    I have the requested dv in another .aspx file.
    I”m still creating individual .aspx files when testing new content. I like being about to just load that page so I can test the new component in a clean enviroment.
    No dynamically loaded content on the test page. So the possibility of features not acting right and any importing errors are not an issue when testing the new component.
    There are also visual concerns.
    We are considering going to only an imperative approach, just not yet.

    I load only the code that the requested dv resides within from another page. I replace the existing dv by inserting the loaded dv into the same div that contains the original dv. (reads badly, sorry)

    Where the declarative way of using a dv, that code is not processed again once it is brought in from another .aspx file. I have tried different approaches but have failed in my attempts so far. That is why I prefer the imperative way.

    Question:
    When is the Sys:If, Sys:CodeBefore, Sys:CodeAfter processed?

    Is it at the same time the “dv:data=”{{data}}”>” code is processed?

    or it is when the itemRender is being executed?

    My guess is the later, but that is only a guess.
    I hope it is the when the itemRender is being executed.

    Off the wall question.

    I read a lot of people question what happens if .js is not enabled. That pages should degrade nicely for them.

    Since most of my work is for small companies and do not get 10s of thousands of hits. I do not try to be all for everyone.

    But, if you are committed to client side code and dynamically loading content, is this really something that we should be concerned with?

    My components, behaviors, controls and a majority of base objects are created in .js. How could you even start to design for both worlds? (.js enabled and .js disabled)

    I see that Tales from an Evil Empire did address this today in his blog. That just seems to increase the workload and I”m not sure it will work in all cases for us.

    Thanks,
    William Apken

  2. Oh, I remembered that I still don”t have a sample which shows how to replace a template with another (which is basically what you”re trying to do, right?). I”ll try to write it today…

  3. Yes. I guess you broke down to its basic level. And that is what I”m looking to do.

    But still I”m not sure if I declare the template with declarative syntax and I want to change the fetch to another entity and may even want to change the fetch query when I change the template.

    how to get the new code parsed?

    That is not happening just when you assign the replacment html.

    It does happen if you create a new dataview and reference the div”s id of the replacement code.

    I would just like the new html being loaded to be parsed again like it does on the init load of the page.

    I never leave the first page that is loaded when a user loads my site. So basically the default.aspx is my master page. (not the MasterPage of Asp.net).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: