Sunday, October 9, 2011

Problem with Using SharePoint Lookup Columns in Word Documents

Document properties give you a rich user experience to maintain SharePoint metadata in word documents. You can create a document content type based word templates and add SharePoint metadata to it through the Quick Parts (in Ribbon go to: Insert ► Quick Parts ► Document Properties) easily.

One of the puzzlepart assignment, I had an issue on maintaining lookup fields in word templates. Lookup fields are displayed as dropdown in word template. The issue was some of the items were missing in the dropdown (which is available in lookup list). When I investigated it I found that the dropdown item count decided based on the default view of the lookup list.

For an example if the default view restricted to display 100 items, then in dropdown shows only 100 items. Same way you can configure the filtering or sorting order in the default view of the lookup list if you want to filter out or sort the items in word template dropdown lookup.

Sunday, February 20, 2011

How to Set SharePoint People Picker Default Value to Current User through JavaScript

With the common SharePoint field types you can specify “[Me]” in the default value property to set the current logged in user. But for the Person or Group field type they haven’t enable this feature. This is a common requirement and I needed to find a good standard approach.

We can achieve this in two scenarios:
  1. After the list item save: We can trigger a workflow and programmatically set the logged in user to the field
  2. Before the list item save: We can modify the list item add new form page to set the current logged in user using JavaScript
In my case, the requirement was second scenario and this blog post is mainly focused on that.

If we are modifying the list item add new form page to achieve this, we need to consider two things:

How to get the current user information in SharePoint context via JavaScript

For this I had to refer SharePoint 2010 - Client Object Model and how to get the logged in user information using SharePoint JavaScript api.

How to set the value to the People Picker control

I found the post on how to manipulate a list form fields using JavaScript but it doesn’t mention how to do it for the People Picker control. Unlike other form fields we can’t uniquely identify the People Picker control in html markup (Other form fields can be identified by the title attribute. Title attribute has set to the field name of list item). Therefore in my approach I had to know the parent element of the People Picker control to identify the People Picker control.

I have bundled this functionality to a JavaScript class and we can reuse it whenever needed. One thing that I learned working with Puzzlepart team was you must simplify your implementation as much as possible and isolate it in a generic manner that we can reuse it other places.

PeoplePicker Class
<script type="text/javascript">

function PeoplePicker(){

    this.context = null;
    this.web = null;
    this.currentUser = null;
    this.parentTagId = null    
    
    this.SetParentTagId = function(id){
        this.parentTagId = id;
    }
    
    this.SetLoggedInUser = function(){
        if(this.parentTagId != null){
            this.getWebUserData();            
        }    
    }
    
    this.getWebUserData = function(){
        this.context = new SP.ClientContext.get_current();
        this.web = this.context.get_web();
        this.currentUser = this.web.get_currentUser();
        this.currentUser.retrieve();
        this.context.load(this.web);
        this.context.executeQueryAsync(Function.createDelegate(this, this.onSuccessMethod), 
                                       Function.createDelegate(this, this.onFailureMethod));
    }    
    
    this.onSuccessMethod = function(){ 
        this.setDefaultValue(this.currentUser.get_title());        
    }

    this.onFailureMethod = function(){
        alert('request failed ' + args.get_message() + '\n' + args.get_stackTrace());
    }    
        
    this.setDefaultValue = function(value){         
        var parentTag = document.getElementById(this.parentTagId);
        if (parentTag != null) {
            var peoplePickerTag = this.getTagFromIdentifierAndTitle(parentTag, 'div', 
                                                    'UserField_upLevelDiv', 'People Picker');
            if (peoplePickerTag) {
                peoplePickerTag.innerHTML = value;
            }            
        }
    }    
    
    this.getTagFromIdentifierAndTitle = function(parentElement, tagName, identifier, title){     
        var len = identifier.length;
        var tags = parentElement.getElementsByTagName(tagName);
        for (var i = 0; i < tags.length; i++) {
            var tempString = tags[i].id;
            if (tags[i].title == title && (identifier == "" || 
                                tempString.indexOf(identifier) == tempString.length - len)) {
                return tags[i];
            }
        }
        return null;
    }
}

</script>
Now you can reuse this in your aspx markup:
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">

<sharepoint:scriptlink localizable="false" name="SP.js" ondemand="true" runat="server"/>  

<script type="text/javascript">

ExecuteOrDelayUntilScriptLoaded(SetWebUserData, "sp.js");

function SetWebUserData() {
    var pplPicker = new PeoplePicker();
    // Set the parent tag id of the people the picker.
    pplPicker.SetParentTagId('ctl00_UserField_containerCell');
    pplPicker.SetLoggedInUser();
}

</script>

</asp:Content>