Reading User Profile Properties from InfoPath forms hosted in Office 365

So SharePoint knows everything about the employee’s in an organisation down to their shoe size, and now its time to utilise this information within InfoPath forms.

With on premise SharePoint its simple case of configuring data connections to use target applications within the secure store etc, with SharePoint online we unfortunately can’t communicate with SharePoint’s web services from InfoPath Forms Services so we have to take a different approach using client side code, here’s how:

Overview

Rather than using InfoPath to retrieve the data, we’ll use client side code that first reads from the User Profile Service (UPS) and then injects the properties into the form.

InfoPath form configuration

To successfully update the form we’re going to need a way to identify which input field our code is updating, the simplest way I’ve found is to make use of the title attribute:

  1. Within InfoPath Designer, open the properties of the input control that you wish to be updated, switch to the advanced tab, then update ScreenTip with the title as I have shown below.
    InfoPathTitle
  2. Publish the form as usual.
  3. Create a web part/publishing page to host the form.
  4. Add an InfoPath Form web part to the page and configure it to show the form.

The code

With the form containing a input field featuring a consistent attribute that we can target and being hosted in a SharePoint page we can now add code:

  1. Add a script editor web part to the page hosting the form
  2. Load the dependant libraries by adding the following to the script editor web part
    <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="/_layouts/15/SP.Runtime.js"></script>
    <script type="text/javascript" src="/_layouts/15/SP.js"></script>
    <script type="text/javascript" src="/_layouts/15/SP.UserProfiles.js"></script>
     
  1. Modify the following code to match the name of the user profile property you would like to read for the current user (Overwrite PreferredName) and the title of the input field you would like to update (Overwrite Employee Name)
   <script type="text/javascript">
   SP.SOD.executeOrDelayUntilScriptLoaded(getUserDetails, 'SP.UserProfiles.js'); 
    function getUserDetails() {
        var clientContext = new SP.ClientContext.get_current();
        var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
        userProfileProperties = peopleManager.getMyProperties();
        clientContext.load(userProfileProperties);
        clientContext.executeQueryAsync(onSuccess, onFail);
    }
    // On success update our form.
    function onSuccess() {
    $( "input[title='Employee Name']" ).val( userProfileProperties.get_userProfileProperties()['PreferredName'] );
    $( "input[title='Employee Name']" ).blur();
        }
    // On fail add an alert with the error message.
    function onFail(sender, args) {
    alert (args.get_message());      
    }
    </script>

Notes:

  • We use SP.SOD.executeOrDelayUntilScriptLoaded to ensure that SP.UserProfiles.js has been loaded before running our function
  • The blur event is required to trigger any InfoPath rules associated with the field your updating, so may not be required for your form
  • This approach could easily be modified for standard SharePoint ASPX forms
  • I’ve recommended adding code to a script editor for ease of demonstration, for real world use your probably better off to saving your scripts to an assets library so they can be re-used and edited easily.

 

Advertisements

Setting a lookup column’s default value in SharePoint Online

For a recent project I needed a lookup column that was hidden and defaulted to a specific list item. On premise this is simple to achieve:

  • Use SharePoint Manager 2013 to set the default value, format of the value needs to be ID;#Title e.g. 1;#Details
  • Set the lookup column to hidden within the site content type – This is a must, otherwise the UI will override the default value

For SharePoint Online I decided to use SharePoint’s REST API to set the lookup column’s default value. To save anyone else from spending time on something that should be simple I’ve created a simple tool for updating the default value of site columns:

Usage

  1. Copy and paste the code in this post into a script editor web part
  2. Enter the display name of the (site) lookup column into the Column Name field
  3. Enter the ID of the list item that the lookup column should default to within the Default Value field
  4. Click Update Column
  5. Check the result by modifying the following rest call to match your site and column, then paste it into the address bar – https://Your Site/_api/web/fields/getbytitle(‘Your Column‘)/defaultvalue

The tool will use Sharepoint’s  status bar to provide the outcome, as shown below:

DefaultValue

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
var statusId = '';
var notifyId = '';
function updateColumn(){
	SP.UI.Status.removeAllStatus(true);
	var colName = document.getElementById("siteColumn").value;
	var defaultValue = document.getElementById("defaultValue").value;
	var webUrl = _spPageContextInfo.webAbsoluteUrl
	if (colName.length == 0 || defaultValue.length == 0){
    	statusId = SP.UI.Status.addStatus("Ensure you have populated both the Column Name & Default values then try again");
    	SP.UI.Status.setStatusPriColor(statusId, 'red');
		}
	else{	
		$.ajax({
  		url: webUrl + "/_api/web/fields/getbytitle('" + colName +"')",
  		type: "POST",
  		data: JSON.stringify({
            "__metadata": { type: "SP.Field" },
            DefaultValue: defaultValue
        }),
          headers: { 
    		"X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
    		"content-type": "application/json;odata=verbose",
    		"X-HTTP-Method": "MERGE"
  		},
  		success: successHandler,
  		error: errorHandler
		});
		function successHandler(){
		statusId = SP.UI.Status.addStatus("Yep we worked");
    	SP.UI.Status.setStatusPriColor(statusId, 'green');
		}
		function errorHandler(error){
		statusId = SP.UI.Status.addStatus("Failed - " + error.statusText);
    	SP.UI.Status.setStatusPriColor(statusId, 'red');
		}
	}
}
</script>
<table cellpadding="5">
<tr>
<th>Column Name (Display Name)</th><th>Default Value</th>
</tr>
<tr><td><input id="siteColumn" ></td><td><input id="defaultValue" ></td></tr>
<tr><td><input style="margin-left:0px;" id="goButton" type="button" value="Update Column" onclick="javascript:updateColumn();"></td><td></td></tr>
</table>

Using search web parts to display relevant content to users

Since the SharePoint 2007 days we’ve been able to utilise audience targeting to display different content to different groups of users, whilst this works well its often not as granular as clients would like. Fortunately SharePoint 2013’s search now makes life easy, here’s how:

To start simple, lets say we need a web part that displays any policy and procedure documents related to the current user’s department. We can do this without a single line of code by using the content search web part (CSWP). Prior to building the search query we’re going to need to know three items:

  1. How to identify policy and procedure documents – In this case they have a content type named “Policies and Procedures”
  2. How to identify the departments that document has been tagged with – The search schema shows a managed property named owstaxIdDBDepartment that contains this information (Search the search schema for the name of your site column to find yours)
  3. How to identify which department the current user belongs to – Within the edit screen of the department user profile property, the name shows as SPS-Department

Using this information we can then build an appropriate search query:

ContentType=”Policies and Procedures” owstaxIdDBDepartment:{User.SPS-Department}

Troubleshooting tip – Setup a simple query to return all policy and procedure documents, set the display template to diagnostic, then use the property mapping setting to display the managed property your using to query against the documents department to confirm exactly what is being returned.

Lets say we want to get a bit more fancy and create a web part that displays news articles that are relevant to the current users skill set. To ensure users don’t miss news posts, we want the web part to return news posts that contain the users skill within any of their managed metadata tags.

The owstaxidmetadataalltagsinfo managed property makes life very easy, it contains the data from all managed metadata fields. So knowing that all news articles have the content type name of “News Articles” and the user profile property that contains the users skills is named SPS-Skills, the query would be as follows:

ContentType=”News Articles” owstaxidmetadataalltagsinfo:{User.SPS-Skills}

For more info on SharePoint’s Keyword Query Language see – https://msdn.microsoft.com/en-us/library/office/ee558911.aspx

rollup2

Consistent text & images within display templates

SharePoint sites that feature different sized images and lines of text within aggregation web parts just don’t look professional. Enforcing ridiculously strict guidelines for content authors is always one option, I wouldn’t fancy suggesting it with a workshop though.

Fortunately Microsoft have given us everything we need to create consistent rollups. as shown below:

rollup2

Images

Image renditions do pretty much all the work, before starting check you have the prerequisites in place:

  • If your on premise the blob cache needs to be configured as detailed here
  • Ensure your using a site with publishing features enabled
  • From Site Settings -> Image Renditions, add a new image rendition specifying the image dimensions you require then make a note of its ID

The image rendition can then be called by appending ?RenditionID=X to your image within the display template. Note replace X with your image ID.

When using publishing pages, I don’t like to enforce a default image rendition as it removes the option for content authors to edit the image rendition from within the page. Instead I take the approach of enforcing the image rendition within the display template, to do this you’ll need to remove the html formatting that’s returned within the managed property like so:

var newsPicture = $getItemValue(ctx, “RollUpImage”);
var newsPictureString = newsPicture.toString();
var newsPictureBefore= newsPictureString.substr(0, newsPictureString.indexOf(‘?’));
var newsPictureURL = newsPictureBefore + “?RenditionID=5” ;

Whilst your there its also a good idea to set a default rollup image like so:

if (newsPictureString.indexOf(“/”) == -1) {
var newsPictureURL = ‘/sites/newshub/PublishingImages/default.jpg?RenditionID=5’;
}

Note – Update your RenditionID and site collection url accordingly.

Finally you need to show your content authors how to work with image renditions.

Text

If the display template is going to be used in the same size web part throughout the site collection, you could simply just trim the text whenever there are more than X characters using the Srch.U.getTrimmedString – More details.

More than likely you’ll want to rollup news into various sized web parts, by using CSS to trim the text you can avoid the need for multiple display templates:

If the field is a single line, you can simply apply the ms-noWrap class to your html element.

For multiple lines you’ll need to create your own class as shown below:

.eventRollupDescription{
line-height:1em;
max-height:3em;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow-y:hidden;
}

The above styles will limit the output to three lines, modify the line-height, max-height -webkit-line-clamp styles to meet your needs.

The amount of lines displayed can then be adjusted at will, for example I have web parts in a custom page layout that has a horizontal web part zone that has a class of .horizontalWebpartZone, and I want only two lines:

.horizontalWebpartZone .eventRollupDescription{
line-height:1em;
max-height:2em;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow-y:hidden;
}

Content Slider Display Template for CSWP

So I know there’s already apps out there, but using the OOTB content search web part provides much more flexibility:

  • Make use of SharePoint’s Keyword Query Language to display any items from within your farm/tenant – Tailoring news posts etc to specific users (More on that another day)
  • Using SharePoint’s image renditions, content authors can easily add rollup images that won’t end up squished or stretched
  • Enable content authors to select which managed properties are used through the web part properties

Through CSS you can also make it look however you like, I’ve opted to create a look as close to possible as the slider on the UK BBC homepage. To save you installing it to see how it looks, here’s a screenshot (Headline News web part):

contentslider5

I opted to use the bxSlider JQuery plugin which is completely free so in turn I can also give away my display templates. Fortunately using design packages its a doddle to get up and running:

  1. Import this display template DBSlider.wsp – Rename extension from .doc to .wsp
  2. Create an image rendition that has an ID of 5 (Suggested name is “News Rollup Image” 250px by 160px, but adjust to meet your needs)
  3. Configure your CSWP, setting both the control and item display templates to be slider

By default the display template is configured to use the article byline and rollup image managed properties from publishing pages, if your content is of another type, simply adjust these managed properties within the web part properties.

SharePoint CRM V1.2 Released

In case you missed it, I recently released version 1.2.0.0 of SharePoint CRM – Download

Along with minor improvements, here are the updates:

  • Projects can now have multiple clients and project managers – Also multiple Contacts related to the client can be added to the project form.
  • Added text filters to allow wildcard case insensitve searching
  • Added error checking for any un-connected date filters
  • Improved User Guide