Using the fetchParameters property to pass values to the web service method

In the previous posts, we’ve seen how to configure the DataView control so that it gets the data from a remote web service. In this post, we’ll see how we can take advantage of the fetchParameters to pass info to the web service. The idea is simple: we’ll update the previous sample so that it renders a table with clickable headers used for sorting the displayed data. Sorting the data will be done on the server. This means we need to start updating the server side code so that the web service method gets the info used for sorting (notice I’m only showing the changes made to the initial code):

public class PeopleService {
    static List<Person> _people = new List<Person>
        {
            new Person{ Name = "luis", Address = "fx"},
            new Person{ Name = "john", Address = "lx"},
            new Person{ Name = "peter", Address = "pt"}
        };
    [OperationContract]
    [WebGet]
    public IEnumerable<Person> GetPeople(SortOrder sort) {
        var ordered = _people.OrderBy( 
p => (sort == SortOrder.Name ?
p.Name : p.Address) ); return ordered; } } public enum SortOrder { Name, Address }

As you can see, changes are really minimal: we’ve added an enumeration used for indicating the sort order that should be applied to the collection and we’ve updated the GetPeople method so that it orders the collection accordingly. Now, let’s see the client code:

<head runat="server">
  <title></title>
  <style type="text/css">
      .sys-template{
          display: none;
      }
  </style>
  <script src="Scripts/MicrosoftAjax/start.debug.js" 
type="text/javascript">
</
script> <script type="text/javascript"> Sys.require([Sys.scripts.jQuery, Sys.scripts.WebServices,Sys.components.dataView],function () { Sys.loadScripts(
[
"PeopleService.svc/jsdebug"], function () { Sys.Application.activateElement(
Sys.get("#view")); $("thead td").click(function () { var view = Sys.get("$view"); view.get_fetchParameters()
.
sort =
(
$(this).text() === "Name" ?
SortOrder.Name :
SortOrder.Address); view.fetchData(); }) }); }); </script> </head> <body xmlns:sys="javascript:Sys" xmlns:dv="javascript:Sys.UI.DataView"> <table> <thead> <tr> <td>Name</td> <td>Address</td> </tr> </thead> <tbody id="view" class="sys-template" sys:attach="dv" dv:autofetch="true" dv:httpverb="GET" dv:dataprovider="{{ PeopleService }}" dv:fetchoperation="GetPeople" dv:fetchparameters="{{ { sort: SortOrder.Name } }}"> <tr> <td>{{name}}</td> <td>{{address}}</td> </tr> </tbody> </table> </body>

 

Most of the code is similar to what we had before. There are, however, some differences:

  • I’ve added JQuery to set a click handler to all the TD elements of the header (I still love jQuery 🙂 );
  • we’ve attached the DataView control to the tbody element of the table. This is the easiest way to define the templates without ending up with crappy HTML (thanks go once again to Dave Reed for pointing me in the right direction);
  • in response to a click event on one of the header TDs, we set the sort parameter to the correct value. In a real world app, I’d check that the user was really asking for a different sorting before starting the remote call which refreshes the control (after all, if the data is already ordered by Name, there really isn’t any need to reorder it again by name, right?);
  • after setting everything up, we refresh the data presented by the control by calling the fetchData method. This method will perform the remote call and will automatically refresh the DataView control with the new sorted data.

And there you go: quick and easy, right? Stay tuned for more on MS AJAX.

Advertisements

~ by Luis Abreu on October 28, 2009.

9 Responses to “Using the fetchParameters property to pass values to the web service method”

  1. .sort = SortOrder[$(this).text()]; 🙂

  2. oh damn, you do really read them, don”t you? 🙂

    thanks.

  3. Luis,

    What is the correct line for the fetchParameters:

    It appears that { orderby: ”FirstName” } is not working for me.

    myDV = Sys.create.dataView(“#view”,
    {
    dataProvider: myDC,
    fetchOperation: “Customer”,
    fetchParameters: { orderby: ”FirstName” },
    autoFetch: true,
    itemTemplate: templates.browseTemplate
    }
    );

    Thank you

  4. Can we see an example of the dataView being created with the Sys.create.dataView not declaratively. Also have the ability to swap out templates( as you have done in a previous post) but have the html be a ?

    Everything starting moving alone real well as long as my templates were .

    Tried to convert templates to a table (still working on my datagrid) and it all broke.

    thank you.

  5. William, you want a sample with templates based on tables? (with swapping)

  6. Yes. With no declarative code. It appears that when you put into the template it breaks.

    If you put a table into the html section it works.
    The code below works:

    Name
    Address

    {{FirstName}}{{LastName}}

    If the template includes this works fine.

    The code below is what makes it break.
    var editHtml = “{{City}}{{State}}{{Zip}}”;

  7. It appears that the coded I wrote about in my last comment is not the cause of the error.

    I changed the code to just list the bindings.
    {{FirstName}}{{LastName}}. It still breaks in the function listed below:

    function Sys$UI$Template$recompile() {
    ///
    var element = this.get_element(),
    code = [” $index = (typeof($index) === ”number” ? $index : __instanceId);n var $component, __componentIndex, __e, __f, __topElements = [], __d = 0, __p = [__containerElement], $element = __containerElement, $context = new Sys.UI.TemplateContext(), $id = function(prefix) { return $context.getInstanceId(prefix); };n $context.data = (typeof(__data) === ”undefined” ? null : __data);n $context.components = [];n $context.nodes = __topElements;n $context.dataItem = $dataItem;n $context.index = $index;n $context.parentContext = __parentContext;n $context.containerElement = __containerElement;n $context.insertBeforeNode = __referenceNode;n $context.template = this;n with($dataItem || {}) {n”],
    nestedTemplates = [];
    this._buildTemplateCode(nestedTemplates, element, code, 0);
    code.push(“}n $context._onInstantiated(__referenceNode);n return $context;”);
    code = code.join(””);
    element._msajaxtemplate = [this._instantiateIn = new Function(“__containerElement”, “__data”, “$dataItem”, “$index”, “__referenceNode”, “__parentContext”, “__instanceId”, code), nestedTemplates];
    }

    the last line of this function is throwing the error.

    It appears it does not like trying to place an outside template into the table body.

    I may have my table formated wrong. I did try to copy your example where you used a table.

    Thank you

  8. william, i”velooked at the code now. you cannot create tables like that. try doing something like this:

    var tmpl = “{{name}}{{address}}”;
    var r = document.createElement(“div”);
    r.innerHTML = tmpl;
    var tpl = r.childNodes[0].childNodes[0];

    then pass tpl to the Template constructor and it should work.

  9. That worked. Thanks.

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

 
%d bloggers like this: