Tag: Client OM

Leveraging Search Web Parts and Display Templates

One of my main focuses the past 4-5 years has been leveraging the Search Infrastructure to help deliver dynamic content to portals and Intranets.  In previous versions of SharePoint I leaned heavily on the underlying APIs to deliver custom solutions.  This was both because the underlying APIs allowed more precise querying and because it gave me full control on what was rendered to the user.

With SharePoint 2013 the Search related web parts went through a pretty major renovation, especially for on-premises customers that have Enterprise CALs.  A series of web parts were created, with a full featured query builder that allows you to create and test your queries through a web interface.  Where the results were previously rendered in XSLT, the new method utilizes regular html and javascript to create the output markup which is then injected into the page.  The overall rendering of the pages is much more dynamic, with support to display each item differently based on the type of content it is.  The potential is limitless. 

I intend for this post to be a bit of a primer on the high level topics.  I’ll be coming out with some specific task-driven follow up posts over the next few weeks that expand on these concepts and get into some examples of things that can be done through these new features. 

Dynamic Content using Search Web Parts

For those that haven’t caught my session Dynamic Content using SharePoint Search here is a brief overview.

The web parts themselves are broken into the following categories:

  • Content Rollup (Enterprise Feature)
  • Search-Driven Content (Enterprise Feature)
  • Search

 

Within the Content Rollup category resides the Content Search web part.  This is a great replacement for the Content Query Web Part (CQWP) available in past versions of SharePoint.  Unlike the CQWP, this utilizes the search service so it can pull matching results from anywhere in your farm, which means you are not limited to the current site collection. 

The web part also supports new, previously unavailable display options including the ability to show the item as a slideshow. 

The Search-Driven Content category contains a series of web parts that are all based on the Content Search web part, with a pre-set query to help you get started.  This includes results that display specific types of content like the Videos, Web Pages, Wiki Pages, Pictures, Pages, and then also results that rely on the analytics features to deliver results pertaining to Popular Items, Recently Changed Items, and Recommended Items.  The pre-configured queries are a great start, and using the query builder form you can dial in the specific results you are looking to display. 

Search Display Templates

All of the search web parts, including the standard Search Results web part that is available in all versions of SharePoint Server as well as the SharePoint Online service within Office 365, then offer the ability to change how your results are rendered using the Search Display Templates.  This is where the real power of the new changes come into play since we can now change how items are rendered by editing the html and javascript in the display templates. 

The display templates are stored in the Master Page Gallery for each site collection.  You can find them by browsing to Site Settings, and clicking the Master pages and page layouts link under the Web Designer Galleries group.  From within the gallery, browse into the display templates directory, and then into the Search directory for search specific display templates. 

A good reference for the included display templates is available here on the TechNet/MSDN website:  http://technet.microsoft.com/en-us/library/jj944947(v=office.15).aspx

Here is a good overview of how to work with the display templates:  http://msdn.microsoft.com/en-us/library/office/jj945138(v=office.15).aspx

Use the Status Bar to Display Active Workflows

Over the past six months I’ve found myself moving more and more towards using the new Client OM for things that I used to use jQuery and SPServices for.  While I still love SPServices, it is not always required and now that I am getting more knowledgeable about how to do things in the Client OM, things are getting a lot easier (although you have to go back to writing CAML).

After a recent session at SharePoint Saturday The Conference an attendee asked me about ways to show a user they have an open workflow task.  After thinking about it, it was pretty similar to something else I had done recently that involved reading for a SharePoint list and adding an item to the status bar using the Client OM.  This particular request involved a little more code in order to properly filter down the task list, but it works like a charm.  It is important to remember that the client OM only works within the given Site Collection, and this particular code as-is will only look at the site the user is on at the time.

If you want this to display on a single page, you can simply add it to the page. In order to have it show up throughout the site though, you will want to add it to the MasterPage. If the MasterPage is used throughout many sites and or site collections, it will show any open tasks for the specific site.

To start off, we will create a div container. I typically put something like this just inside the tag of the MasterPage. Add in some global variables and then add in the Ajax Execute/Delay command that will call the first method, getUser() when the page is fully loaded.

   <div id="SetStatus"><script type="text/ecmascript" language="ecmascript">
    var url = '';
    var statusId = '';
    var isitDlg = window.location.href.match(/isDlg/i) != null;
    var taskOutput;
    var context = null;
    var web = null;
    var curUser = null;

    if (!isitDlg) {
        ExecuteOrDelayUntilScriptLoaded(getUser, "sp.js");
    }
</script></div>[/sourcecode]   

Next, within the script block we will add the methods to support getUser(). These methods will get the current user's information which is needed to be able to load only the current user's assigned tasks.

[sourcecode language="js"] function getUser() { context = new SP.ClientContext.get_current(); web = context.get_web(); curUser = web.get_currentUser(); curUser.retrieve(); context.load(web); context.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod), Function.createDelegate(this, this.onFailureMethod)); } function onSuccessMethod(sender, args) { var user = web.get_currentUser(); LoadNotifications(); } function onFailureMethod(sender, args) { alert('Error: ' + args.get_message() + 'n' + args.get_stackTrace()); }

With the user’s name available we can now read the list items from the local Task List that are active and assigned to the user. If successfull the (ReadListItemSucceeded() method is called otherwise if an error is raised the ReadListItemFailed() is called.

function LoadNotifications() {  	
var listTitle = "Tasks";  	
context = SP.ClientContext.get_current();  	
var list = context.get_web().get_lists().getByTitle(listTitle);  	
var camlQuery = new SP.CamlQuery();  	
camlQuery.set_viewXml("<view><query><viewfields><fieldref name="ID" /><fieldref name="Title" /><fieldref name="FileDirRef" /><fieldref name="StartDate" /><fieldref name="DueDate" /></viewfields><where><and><eq><fieldref name="AssignedTo" /><value type="User">" + curUser.get_title() + "</value></eq><or><eq><fieldref name="Status" /><value type="Choice">In Progress</value></eq><eq><fieldref name="Status" /><value type="Choice">Not Started</value></eq></or></and></where></query></view>");  	
this.listItems = list.getItems(camlQuery);  	
context.load(listItems);  	
context.executeQueryAsync(ReadListItemSucceeded, ReadListItemFailed);  
}  

The returned list of tasks is now processed and the output is prepared. If tasks are prepared, the SetStatus() method is called to show the status bar message.

function ReadListItemSucceeded(sender, args) {  	
var itemCount = 0;  	
taskOutput = " <div id="tasks"> <table width="800"> <tbody> <tr style="font-weight: bold"> <td width="500">Task</td> <td width="150">Start Date</td> <td width="150">Due Date</td></tr>";  	var items = listItems.getEnumerator();          
while (items.moveNext()) {             
itemCount += 1;             
var listItem = items.get_current();             
var isLate = false;             
taskOutput += "<tr><td><a href="&quot; + listItem.get_item(" FileDirRef') + "/DispForm.aspx?ID=" + listItem.get_item('ID') + "' target='_top'>" + listItem.get_item('Title') + "</a></td><td>" + listItem.get_item('StartDate') + "</td><td>" + listItem.get_item('DueDate') + "</td></tr>";         
}         
taskOutput += "</table></div>";         
if (itemCount > 0) {             
SetStatus("Reminder: ", "You have a workflow task! <a href="javascript:ShowTasks()">View open Workflow Tasks</a>", isLate);         
} 
} 
function ReadListItemFailed(sender, args) {         
alert('Error: ' + args.get_message() + 'n' + args.get_stackTrace()); 
} 

The SetStatus() method shows how simple it is to work with the Client OM. The SP.UI.Status.addStatus call will post the message including the title and the body of the message. We then make a second call to SP.UI.Status.setStatusPriColor to change the color of the bar. Pretty simple, yet so powerfull!

function SetStatus(title, message, isLate) { 	
statusId = SP.UI.Status.addStatus(title, message, false);         
if (isLate) {             
SP.UI.Status.setStatusPriColor(statusId, 'red');         
}         
else {             
SP.UI.Status.setStatusPriColor(statusId, 'yellow');         }     } 

The last method is the ShowTasks method which is the javascript function that is called from within the status messages to show a simple output inside of the Client OM’s ModalDialog. First format the display options for the window and then call the SP.UI.ModalDialog.showModalDialot() method.

function ShowTasks() {  	
var _html = document.createElement('div');  	
_html.innerHTML = taskOutput;  	
var options = { html: _html, autoSize:true, allowMaximize:true, title: 'Open Workflow Tasks', showClose: true };  	
var dialog = SP.UI.ModalDialog.showModalDialog(options);  
}  

Not a lot of code to provide a very usefull solution that does not require anything to be deployed to the server. Below are screenshots of the solution in action.

Open Workflow Tasks Status

Open Workflow Tasks Listing

There are definitely some things that can be done to better format the output of the ModalDialog, but you get the idea. This is just one way to leverage the Client OM for some very useful business features.

%d bloggers like this: