Navigate Up
Sign In
Supporters of Developer
Web

Applying the MVVM pattern to create SharePoint list-driven interactive tools using Knockout

Item is currently unrated. Press SHIFT+ENTER to rate this item.1 star selected. Press SHIFT+ENTER to submit. Press TAB to increase rating. Press SHIFT+ESCAPE to leave rating submit mode.2 stars selected. Press SHIFT+ENTER to submit. Press TAB to increase rating. Press SHIFT+TAB to decrease rating. Press SHIFT+ESCAPE to leave rating submit mode.3 stars selected. Press SHIFT+ENTER to submit. Press TAB to increase rating. Press SHIFT+TAB to decrease rating. Press SHIFT+ESCAPE to leave rating submit mode.4 stars selected. Press SHIFT+ENTER to submit. Press TAB to increase rating. Press SHIFT+TAB to decrease rating. Press SHIFT+ESCAPE to leave rating submit mode.5 stars selected. Press SHIFT+ENTER to submit. Press SHIFT+TAB to decrease rating. Press SHIFT+ESCAPE to leave rating submit mode.

 

Editor's note: Contributor Matt Menezes is a Senior Solutions Consultant at Ignia.

MVC, MVP, MVVM. They’re common acronyms that any developer worth their salt would have at least a vague understanding of what they mean and entail. I remember doing an MVC hands-on lab at Tech-Ed 2-3 years ago in ASP.NET for my own curiosity, see what all the fuss was about. Having been in the SharePoint realm for the past 3 and a half years though it’s something that I never thought would have had much application in my day to day job. Surely it was just left to the ASP.NET crowd, nothing to do with SharePoint. How wrong I was.

To be honest this article could go on forever with explanations and definitions, examples and possibilities. What I’ve since found when researching for this post however is that the information available on the net is actually pretty comprehensive. Unsure what the difference is between the various view-model design patterns? Take a look at Niraj Bhatt’s post on MVC vs. MVP vs. MVVM. In fact somewhat to my surprise there are even a number of quality SharePoint related posts in regards to implementing MVVM. The majority of them relate to MVVM in Silverlight hosted in SharePoint – you can read up on a great article series by Andrew Connell regarding Silverlight, MVVM & SharePoint. There’s a quality post by Shailen Sukul regarding Applying MVVM Principles to SharePoint 2010 Development. There’s even a post on Using MVVM with Office365 and SharePoint 2010 REST API by Sahil Malik.

Sahil’s post is somewhat similar to my own. The reason being, we’ve both implemented the MVVM pattern using Knockout – a library to ‘Simplify dynamic JavaScript UIs by applying the Model-View-View Model (MVVM) Pattern’. There is a difference however – where Sahil had the luxury of using the SharePoint 2010 REST APIs which go hand in hand perfectly for this purpose, my task was to implement it in MOSS 2007.

The tools created using this method are a part of the suite of tools that exist on the Career Centre Portal including the Resume Builder, Slider tools, Choices and Hands On, Career Possibility Generator, Card Sort tools and multiple forms throughout the site. A number of developers have played a large part in the creation of these tools and forms including Paul Maddox, Elliot Wood, Lay Hooi Tan and myself. Some are SharePoint list-driven and others are CRM-driven. For the purpose of this article I’ll focus on the Career Possibility Generator.

So how does Knockout work? It could really do with a post of its own. I’d suggest reading the documentation for a full explanation of how it works and its capabilities. Trying to keep it simple however, essentially you use data-binds to map UI elements to values stored in a data model. If you define the value as ‘observable’ you ensure that updates to the UI are reflected in the model and vice-versa. Knockout also harnesses the jQuery.tmpl template engine to render repeatable blocks of code.

It’s driven really well by using a JSON object as the underlying data model. This is why it ties in so nicely with the SharePoint 2010 REST services – you can quite easily pull back a JSON object instead of an Atom response via those services and use it within the Knockout framework. To get around this missing functionality an ASHX handler was created to return the JSON object for us. This is quite easy to do – the generic shell of the handler would look something like that shown below:

public class MyHandler : IHttpHandler
{
    #region IHttpHandler Members

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        List<CloudListItem> items = new List<CloudListItem>();
        // Retrieve items from SharePoint and populate into the generic list
        JavaScriptSerializer ser = new JavaScriptSerializer();
        string jsonObject = ser.Serialize(items);
        context.Response.Clear();
        context.Response.ContentType = "application/json";
        context.Response.Write(jsonObject);
    }

    #endregion
}

public class CloudListItem
{
    // Various properties to return in the JSON object
}

The next step is to bind the returned JSON object to Knockout and in turn allow Knockout to bind the values to the UI using applyBindings.

<script id="Occupations_Cloud_Tmpl" type="text/x-jquery-tmpl">
    <li class="cloud${Count}"><a target='_blank' href="${PageUrl}">
      <label data-bind="text:Title"></label>
    </a></li>
</script>

<div id="tag-cloud">
    <ul id="occupations-cloud"
        data-bind="template: {name: 'Occupations_Cloud_Tmpl', foreach: viewModel.Cloud}">
    </ul>
</div>

<script type="text/javascript">
    $.getJSON('/_controltemplates/ccosdportal/handlers
               /ListToJsonHandler.ashx?ListName=NormalisedKSA
               &Web=occupations', function(data){
        //viewModel.Cloud = ko.mapping.fromJS(data);
        viewModel.Cloud = data;
        $.each(viewModel.Cloud, function(index, value) {
            value.Count = ko.observable(0);
        });
        ko.applyBindings(viewModel.Cloud);
    });
</script>

Essentially what the above code will result in is an unordered list of Occupation profile links with a distinct class applied. I’ve left in the comment above to demonstrate one of the gotchyas I encountered using Knockout. By using ko.mapping.fromJS() you’re essentially ensuring that all properties within the JSON object are observable. This causes some memory issues if the object is too large and can result in the following warning in Internet Explorer browsers:

2012-01-03-ApplyingMVVMPattern-01.png

The only thing left to explain here is how the ‘observable’ functionality works. The tool itself includes a number of checkboxes which users can select which in turn drives how the cloud looks on the screen. The checkboxes are mapped in SharePoint lists to various occupations and thus when a checkbox is selected that maps to a given occupation, the class applied to the relevant list item is modified to reflect that link. As you may have noticed, the only observable property in the object is the ‘Count’ which is used in the list item class=”cloud${Count}”. By incrementing the Count value in the model, the UI is updated to reflect the new value and hence changes the class of the list item, changing the way it displays on the screen.

function AdjustCloud(checkbox) {
    var addValue = -1;
    if (checkbox.checked) addValue = 1;

    $.getJSON('/_controltemplates/ccosdportal/handlers
               /ListToJsonHandler.ashx?ListName=OccupationKSA
               &Web=occupations&KSAID=' + checkbox.value, function(data){
    if (data.length > 0)
    {
        $.each(data, function(ind, dtwd) {
            var dtwdVal = dtwd.DTWDANZSCO;
            $.each(viewModel.Cloud, function(index, value) {
              var clouddtwdVal = value.DTWDANZSCO;
              if (clouddtwdVal == dtwdVal)
                if (((viewModel.Cloud[index].Count() + addValue) >= 0) &&
                   ((viewModel.Cloud[index].Count() + addValue) <= 9))
                       viewModel.Cloud[index].Count(viewModel.Cloud[index].Count() + addValue);
            });
        });

         HideItems();
    }
    });
}

A visual example of the tool can be seen below.

2012-01-03-ApplyingMVVMPattern-02.png

If you take the time to look at the Career Possibility Generator and all the tools throughout the Career Centre Portal you’ll get an appreciation of how powerful it is to leverage the MVVM pattern via Knockout to create highly interactive applications within SharePoint.

This article was originally posted on Matt's blog SPMatt

Categories: SharePoint; Javascript and jQuery; MOSS; WSS; 2007; 2010

Comments

John Liu

spservices.codeplex.com

If you use Knockout in conjunction with spservices.codeplex.com then you can get list data in a pure jquery-based solution, without having to deploy your asha file. A pure jquery based solution would be easy to deploy to Office 365 as well. SPServices wraps around the SOAP webservices and lets you query data in both 2007 and 2010. Though in 2010, ClientContext is already loaded so that'd be quicker to use.

Posted 04-Jan-2012 by John Liu
John Liu

Thanks

Great article by the way. Knockout looks great!

Posted 04-Jan-2012 by John Liu
russell

knowckout with listdata,svc

Thanks for publishing this Article. I'm currently working on a Prototype project to uses KO with SP. I see a lot of opportunity here. Just curious... why did you write a custom service to return JSON, rathee than listdata.svc?

Posted 11-Jan-2012 by russell
Matt Menezes

Custom handler

Hey John - wasn't aware of that library, wish I had, it looks like it would fit the bill nicely. There was a little extra processing going on with randomised sorting and the like in the handler but knowing jQuery that wouldn't have been too hard to incorporate :) Russell - the reason why the handler was used rather than listdata.svc is because the site was built on MOSS rather than SP2010 - would have loved to have been able to use the REST services!

Posted 13-Jan-2012 by Matt Menezes

Notify me of comments to this article

E-mail:
   

Add Comment

Title:

 
Comment:
Email:

   


Name:

 
Url: