I was creating a SharePoint hosted app in SharePoint 2013. In the app I have placed a client side people picker to select the reviewers. When I install and run the app, people picker is working well but showing all the users. I want to restrict the users listed from a SharePoint group. To restrict I have made the below code changes. Here are the steps to restrict the client people picker to particular SharePoint group.

I have created a group named Reviewers in the host web and added some sample users.

Groups

I have created a SharePoint hosted app placed the below code which will refer the client people picker in Default.aspx.


<!-- For People Picker -->

<SharePoint:ScriptLink name="clienttemplates.js" runat="server" LoadAfterUI="true" Localizable="false" />

<SharePoint:ScriptLink name="clientforms.js" runat="server" LoadAfterUI="true" Localizable="false" />

<SharePoint:ScriptLink name="clientpeoplepicker.js" runat="server" LoadAfterUI="true" Localizable="false" />

<SharePoint:ScriptLink name="autofill.js" runat="server" LoadAfterUI="true" Localizable="false" />

<SharePoint:ScriptLink name="sp.js" runat="server" LoadAfterUI="true" Localizable="false" />

<SharePoint:ScriptLink name="sp.runtime.js" runat="server" LoadAfterUI="true" Localizable="false" />

<SharePoint:ScriptLink name="sp.core.js" runat="server" LoadAfterUI="true" Localizable="false" />

<!--- -->

In the PlaceHolderMainsection place a div with ID.

In the App.js file added the below methods. I have used the REST API to get the Id of the SharePoint group and pass it to the Client People picker SharePointGroupID properties.


var hostweburl;

var appweburl;

var reviewGroupId;

// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model

$(document).ready(function () {

hostweburl =

decodeURIComponent(

getQueryStringParameter("SPHostUrl")

);

appweburl =

decodeURIComponent(

getQueryStringParameter("SPAppWebUrl")

);

loadDependentScripts();

});

function loadDependentScripts() {

var scriptbase = hostweburl + "/_layouts/15/";

// Load the js files and continue to the successHandler

$.getScript(scriptbase + "SP.Runtime.js",

function () {

$.getScript(scriptbase + "SP.js",

function () { $.getScript(scriptbase + "SP.RequestExecutor.js", LoadInitial); }

);

}

);

}

function LoadInitial() {

var executor = new SP.RequestExecutor(appweburl);

executor.executeAsync({

url: appweburl + "/_api/SP.AppContextSite(@target)/web/SiteGroups/getbyname('Reviewers')?@target='" + hostweburl + "'",

method: "GET",

headers: { "Accept": "application/json;odata=verbose" },

success: getGroupIdSuccessHandler,

error: getGroupIdErrorHandler

});

}

function getGroupIdSuccessHandler(data) {

var jsonObject = JSON.parse(data.body);

reviewGroupId = jsonObject.d.Id;

initializePeoplePicker('reviewerDiv',reviewGroupId);

}

function getGroupIdErrorHandler(data, errorCode, errorMessage) {

alert("Could not get the information:" + errorMessage);

}

function initializePeoplePicker(peoplePickerElementId, Id) {

// Create a schema to store picker properties, and set the properties.

var schema = {};

schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';

schema['SearchPrincipalSource'] = 15;

schema['ResolvePrincipalSource'] = 15;

schema['AllowMultipleValues'] = false;

schema['MaximumEntitySuggestions'] = 50;

schema['Width'] = '280px';

schema['SharePointGroupID'] = Id;

SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, null, schema);

}

function getQueryStringParameter(paramToRetrieve) {

var params =

document.URL.split("?")[1].split("&");

var strParams = "";

for (var i = 0; i < params.length; i = i + 1) {

var singleParam = params[i].split("=");

if (singleParam[0] == paramToRetrieve)

return singleParam[1];

}

}

Now I install and access the App my people picker is allowing to select users who are available in “Reviewers” SharePoint group.

result1

result2

Note: Give read permission to the App to access the host site collection.

Posted by: R Manimaran | April 27, 2015

Applying Dynamic Templates in KnockoutJs in Table

I was exploring the Knockout JS for my data-binding with my SharePoint 2013 REST API output. My requirement was to bind my REST API output as a Table format and do the CRUD Operation on the table itself.

Knockout 3.0 offers the SimpleGrid to bind your output to a grid view with pagination. But in the same row itself I need to provide the option to do the edit/Save/ Delete operations. So I went for normal table bindings.

Knockout offers the template binding which I used to dynamically changing the binding logic (view/Edit Mode).

View:

<table class="tab-table">
 <thead>
 <tr>
 <th><b>Article</b></th>
 <th><b>Content</b></th>
 <th>&nbsp;</th>
 <th>&nbsp;</th>
 </tr>
 </thead>
 <tbody data-bind="template :{name:currentTemplate,foreach:articles}">
 </tbody>
 </table>

Read-Only Template Script:


<script id="readOnly" type="text/html">
<tr>
<td><span data-bind="text:title"></span></td>
<td><span data-bind="text:content"></span></td>
<td><input type="button" value="Edit" data-bind="click: function() { viewModel.selectedMode($data) }"/></td>
<td><input type="button" value="Delete"/></td>
</tr>
</script>

Edit Template Script:

<script id="editMode" type="text/html">
   <tr>
       <td><input type="text" data-bind="value:title"></input></td>
       <td><input type="text" data-bind="value:content"></input></td>
       <td><input type="button" value="Cancel" data-bind="click: function() {viewModel.reset();}"></input></td>
       <td><input type="button" value="Save"></input></td>
   </tr>
</script>

In the above I have created two templates, one to apply my read-only databinding and another to have textbox to do edit operations.

View Model:

var viewModel = {
   
    articles: [{
        id: 1,
        title: "KnockOut Templating",
        content: "Content for Knockout goes here."
    }, {
        id: 2,
        title: "SharePoint 2013 REST API",
        content: "Content for SharePoint."
    }, {
        id: 3,
        title: "Knockout with SharePoint",
        content: "Content for knockout and SharePoint."
    }],
    
    selectedTemplate: ko.observable("readOnly"),
    selectedMode: ko.observable(),    
};

viewModel.currentTemplate = function (tbl) {
    return tbl === this.selectedMode() ? 'editMode' : this.selectedTemplate();
}.bind(viewModel);

viewModel.reset = function (t) {
    this.selectedMode("editMode");
};
ko.applyBindings(viewModel);

After applying the above template, by default it will load my read-only output.(added some CSS to change the look of the table)

readonlyTemplate

On Clicking the Edit button my edit mode template will be applied and allow the user to do editing. On clicking the cancel button it will change the template back to the read-only.

EditModeTemplate

In the previous article I have explained about using Handlebars template and SharePoint data. For formatting the Date Time I have used Moment.js file. It has lot of helper functions and formatting options to work with Date Time.

When displaying the data time, Moment.js provides an option to change the locale. By default it will print in English. Locale details is available in the separate script file Moment.locale.js.

Include Moment.js and Moment.locale.js to project.

NugetMoment

The above command will install the following files in your project’s script folder.

  • Moment-with-locales.js
  • Moment-with-locales.min.js
  • Moment.js
  • Moment.min.js

To do it offline, download the above files from Momentjs.com and include to your project.

In the previous example I have wrote a Handlebar Helper method where i have used the Moment.js to format the date. Let we add the locale details to change the data time display.

English Locale:


<script>

    Handlebars.registerHelper("FormatDate", function (date) {              

        moment.locale("en");       

        return moment(date.toString()).format('LLLL');       

    });

</script>

Here is the output

englishLocale

French Locale:


<script>

    Handlebars.registerHelper("FormatDate", function (date) {              

        moment.locale("fr");       

        return moment(date.toString()).format('LLLL');       

    });

</script>

Output

frenchLocale

Good thing is it support my mother tongue “Tamil”. Change the locale to “ta” and the resulted output in tamil.

tamillocale

Following are the list of locales supported by Moment.js

availableLocale

In SharePoint 2010 and 2013 when working with large list (which contains large amount of items more than 5000) we may experience the Threshold issue on List View with the below error.

Threshold

Here why 5000?

This limit is not related with SharePoint. It’s related to Microsoft SQL server. SharePoint uses SQL server as the database tables to store your list values.

  • In SQL server, mostly uses the row-level locking to avoid database contention and to ensure accurate update without impacting the other users who are accessing the other rows.
  • When we did a Select/Update operation and as a result of this consider 5000 rows are affected which causes the SQL server to lock all the 5000 rows at once.
  • But instead of doing so, for SQL server it is efficient to escalate the lock to the top level object (i…e to the Table) and lock the whole table at once, until that operation gets completed.

This actual number will not be always 5000. It depends on the amount of database operation you are performing, your site and its configuration.

When this escalation happens, other users will not able to access the whole table. Hence this threshold is maintained in the SharePoint to avoid the performance degradation.

Here is an article which will help you understand the SQL SERVER Lock escalation with example.

http://aboutsqlserver.com/2012/01/11/locking-in-microsoft-sql-server-part-12-lock-escalation/

In the above situation we need to create indexed columns on the list and perform the list view operation.

Posted by: R Manimaran | December 12, 2014

SharePoint 2013: Using HandleBars.js in SharePoint –Part 3

In Part1, we have seen how to create a Handlebars template and use it SharePoint 2013 REST API output.

In Part2, we have seen how to format a SharePoint date time value using Momemt.js

In this article let us see if we have a Lookup Field column in the list.

I have created a new SharePoint List named “Domain”. In the “Employees” List I have added the title column of the Domain list as a Lookup Field. Below is the view of the Employees list after adding my Lookup column.

EmployeesDomainList

For the Lookup column the REST API JSON output will be different.

REST API URL Endpoint:

/_api/web/lists/getbyTitle(‘Employees’)/items?$select=Title,Created,Modified,Domain/Id,Domain/Title&$expand=Domain/Id,Domain/Title

The JSON output for the above will be like below. Inside the Domain node we are having the title value of the Lookup field.

JSON output

We need to include the above Lookup field in the HandleBars template. So our updated template will be as below.


<!-- Handlebar Js Template Starts Here -->
<script id="employees-template" type="text/x-handlebars-template">
<table>
<thead>
<th>Employee Name</th>
<th>Designation</th>
<th>Location</th>
<th>Expert</th>
<th>Domain</th>
<th>Created</th>
<th>Modified</th>
</thead>
<tbody>
{{#results}}
<tr>
<td>{{Title}}</td>
<td>{{EmpDesignation}}</td>
<td>{{Location}}</td>
<td>{{SME}}</td>
{{#Domain}}
<td>{{Title}}</td>
{{/Domain}}
<td>{{FormatDate Created}}</td>
<td>{{FormatDate Modified}}</td>
</tr>
{{/results}}
</tbody>
</table>
</script>

Helper Function for format date


<script>
Handlebars.registerHelper("FormatDate", function (date) {
var format = 'M/DD/YYYY';
return moment(date.toString()).format('LL');
});
</script>

On running this script we will have the below output in the page.

DomainOutput

Happy coding..

Posted by: R Manimaran | December 9, 2014

SharePoint 2013: Using Handlebarjs in SharePoint- Part 2

In the part1 we have seen how to create a Handlebarjs template and merge our REST API output with that template. In that output the date time values of Created and Modified is not well formatted. Below is the un-formatted output.

handlebarjsoutput

In this we will use Moment.js to do formatting.

Momemt.js

  • js help us to parse, validate, manipulate and display dates in the JavaScript.
  • It’s having rich set of methods to format the date string.
  • You can download the moment.js from here

In the Handlebars we can create our custom methods to do additional functionality. Using the RegisterHelper we can create our custom method. Let’s create a method named “FormatDate” which will accept a parameter.


<script>
Handlebars.registerHelper("FormatDate", function (date) {

return moment(date.toString()).format('LL');

});

</script>

Some of the Moment.js Format strings;

momentjsFormates

To Call the Format Date function we need to change the HandleBars Template we have designed. Below is the updated template.


<script id="employees-template" type="text/x-handlebars-template">

<table>

<thead>

<th>Employee Name</th>

<th>Designation</th>

<th>Location</th>

<th>Expert</th>

<th>Created</th>

<th>Modified</th>

</thead>

<tbody>

{{#results}}

<tr>

<td>{{Title}}</td>

<td>{{EmpDesignation}}</td>

<td>{{Location}}</td>

<td>{{SME}}</td>

<td>{{FormatDate Created}}</td>

<td>{{FormatDate Modified}}</td>

</tr>

{{/results}}

</tbody>

</table>
</script>

Now the output of my page will be like below.

DateFormattedoutput

Posted by: R Manimaran | December 8, 2014

Using Handlebarsjs in SharePoint 2013 with REST API- Part1

When you build the application as client side code using JavaScript, you may come up with the situation to do update the values on the HTML to display. We use JQuery or vanilla JavaScript to do so. To do this easy we can use the different Javascript templating. Some of them are

  • Handlebarsjs
  • Mustache
  • Underscore js
  • EJS

Of the above handlebars.js is easy to learn.

Handlebarjs:

  • js is an extension of the Mustache javascript templating language.
  • It’s supersedes Mustache.js
  • Most advanced Feature rich and popular JavaScript Templating language.

Let us start using this Templating language in a SharePoint project.

Pre-Requisites:

  • Knowledge on SharePoint
  • SharePoint 2013 REST API
  • Client–Side scripting

Before going to the example we need to have some files which we need to add reference to our project. They are

I will explain the 3rd reference in the example. I have a SharePoint List named “Employees” and below are the contents.

EmployeesList

We will access the above list using SharePoint REST API and display the same in a page using Handlebars.

References:

 
<script type="text/javascript" src="/_layouts/15/sp2013/jquery-1.10.2.min.js"></script>

<script type="text/javascript" src="/_layouts/15/sp2013/handlebars.js"></script>

<script type="text/javascript" src="/_layouts/15/SP2013/moment.min.js"></script>

HandleBars.js Template

 


<!-- Handlebar Js Template Starts Here -->

<script id="employees-template" type="text/x-handlebars-template">

<table>

<thead>

<th>Employee Name</th>

<th>Designation</th>

<th>Location</th>

<th>Expert</th>

<th>Created</th>

<th>Modified</th>

</thead>

<tbody>

{{#results}}

<tr>

<td>{{Title}}</td>

<td>{{EmpDesignation}}</td>

<td>{{Location}}</td>

<td>{{SME}}</td>

<td>{{Created}}</td>

<td>{{Modified}}</td>

</tr>

{{/results}}

</tbody>

</table>

</script>

REST API to call SharePoint:

 Below code is having REST endpoint for accessing the Employees List. On the call success the HandleBarJs template which we can created above will be called and loaded with the REST API data output.


function loadSPEmployees() {

var endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbyTitle('Employees')/items?$select=Title,SME,Location,EmpDesignation,Created,Modified”;

var headers = {

"accept": "application/json;odata=verbose"

}

jQuery.ajax({

url: endPointUrl,

type: "GET",

headers: headers,

success: function (data) {

var source = $("#employees-template").html();

var template = Handlebars.compile(source);

var output = template(data.d);

$("#content").html(output);

},

error: function (err) {

alert("Error Occured:" + JSON.stringify(err));

}

});

}

In the Page place a div with the Id “Content”. After the handlebar compile the code the result will be added to this div.

<div id=”content”></div>

On calling the loadSPEmployees method we will get the below output. (I have added some CSS to format the table)

handlebarjsoutput

In the above output the date columns (Created and Modified) are showing the SharePoint date time format. Let we format that in the next article using Moment.js.

Posted by: R Manimaran | November 28, 2014

Creating Navigation under Parent in SharePoint 2013 using REST API

In the Previous blog post we have seen how to create a Navigation using REST API in SharePoint 2013. Using that the Navigation will be created at the end. Suppose consider I have a parent Navigation node and I need to create my new Navigation under that. To do we need to use the below end point.

REST End Point URL: /_api/Web/Navigation/GetNodeById(1031)/children

Here the value 1031 is the ID of the parent Node. You can get that using the GET verb of the below endpoint.

/_api/web/Navigation/QuickLaunch?$expand=children&$select=Title,Children/Title,Children/Id

The REST Output will be like below

RESTOutputNavigation

function createNavigationonHome() {
 var endPointUrl = "http://pwsp2013/_api/Web/Navigation/GetNodeById(1031)/children";
 var headers = { 
 "accept": "application/json;odata=verbose",
 "content-Type": "application/json;odata=verbose",
 "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
 }
 var call = jQuery.ajax({
 url: endPointUrl,
 type: "POST",
 data: JSON.stringify({
 "__metadata": { type: "SP.NavigationNode" },
 'IsExternal': true,
 'Title': "Blog",
 'Url': "http://www.rmanimaran.wordpress.com"
 }),
 headers: headers
 });
 call.done(successHandler);
 call.fail(failureHandler);
}

function successHandler(data, textStatus, jqXHR) {
 SP.UI.Notify.addNotification("Navigation created Successully", false);
 }
function failureHandler(errorMessage) {
 alert("Request Failed: unable to Navigation: " + JSON.stringify(errorMessage));
}

Navigation OnParent

Posted by: R Manimaran | November 12, 2014

SharePoint 2013: Working on Navigation using REST API

SharePoint 2013: Working on Navigation using REST API:

I have not find many articles on Navigation using REST API in the internet. Hope this post will be useful for someone or may be to me in future J

Navigation in SharePoint has two types.

  • Creating Navigation in the Quick Launch( i..e Left Navigation)
  • Creating Navigation in Top Navigation bar (i..e Top links on the page)

To create the above navigations we have separate endpoints respectively

QuickLaunch EndPoint :/_api/web/Navigation/QuickLaunch

TopNavigation EndPoint: /_api/web/Navigation/TopNavigationbar

In the below example I have added a link to my blog at the end of the existing links. I have used Jquery to call the REST API

Creation in Quick Launch bar:

//Create a Quicklaunch Navigation
function createNavigation() {
    var endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/navigation/QuickLaunch";
    var headers = {
        "accept": "application/json;odata=verbose",
        "content-Type": "application/json;odata=verbose",
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
    }
    var call = jQuery.ajax({
        url: endPointUrl,
        type: "POST",
        data: JSON.stringify({
            "__metadata": { type: "SP.NavigationNode" },
            'IsExternal': true,
            'Title': "Blog",
            'Url': "http://www.rmanimaran.wordpress.com"
        }),
        headers: headers
    });
    call.done(successHandler);
    call.fail(failureHandler);
}
function successHandler(data, textStatus, jqXHR) {
   SP.UI.Notify.addNotification("Navigation created Successully", false);
  }
function failureHandler(errorMessage) {
    alert("Request Failed: unable to Navigation: " + JSON.stringify(errorMessage));
}

Quick Launch Navigation

Creation in Top Navigation:


function createNavigation() {
  var endPointUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/navigation/TopNavigationbar";
    var headers = {
        "accept": "application/json;odata=verbose",
        "content-Type": "application/json;odata=verbose",
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
    }
    var call = jQuery.ajax({
        url: endPointUrl,
        type: "POST",
        data: JSON.stringify({
            "__metadata": { type: "SP.NavigationNode" },
            'IsExternal': true,
            'Title': "Blog",
            'Url': "http://www.rmanimaran.wordpress.com"
        }),
        headers: headers
    });
    call.done(successHandler);
    call.fail(failureHandler);
}

function successHandler(data, textStatus, jqXHR) {
   SP.UI.Notify.addNotification("Navigation created Successully", false);
  }
function failureHandler(errorMessage) {
    alert("Request Failed: unable to Navigation: " + JSON.stringify(errorMessage));
}
Top Navigation

Top Navigation

SharePoint 2010 Creating Custom Ranking Model – with Example – Part 2

In the part 1 we have created the custom Ranking model which holds our custom managed property to give more weight-age while doing search.

Let’s use the Keyword Query class to test our ranking model. Add reference to the below namespaces.


using Microsoft.Office.Server.Search.Query;

using Microsoft.Office.Server;

public void Search()

{

//Keyword provided for the Search

string userKeyword = "Manimaran";

KeywordQuery keywordQuery = new KeywordQuery(SPContext.Current.Site);

keywordQuery.ResultTypes = ResultType.RelevantResults;

keywordQuery.EnableStemming = true;

keywordQuery.TrimDuplicates = false;

keywordQuery.IgnoreAllNoiseQuery = true;

//managed properties

keywordQuery.SelectProperties.Add("EmpId");

keywordQuery.SelectProperties.Add("EmpName");

keywordQuery.SelectProperties.Add("EmpDOB");

keywordQuery.SelectProperties.Add("EmpDOJ");

keywordQuery.SelectProperties.Add("HitHighlightedSummary");

keywordQuery.SelectProperties.Add("Filename");

//Set my Custom Ranking model Id

keywordQuery.RankingModelId = "1786318d-cbcc-4c06-9e9f-fe5d3f12279e";

//RankingModel is my Custom Search Scope

keywordQuery.QueryText = "\"" + userKeyword + "\" scope:\"RankingModel\" IsDocument:\"True\"";

//execution

ResultTableCollection searchResults = keywordQuery.Execute();

DataTable relevantResults = new DataTable();

relevantResults.Locale = CultureInfo.InvariantCulture;

if (searchResults.Exists(ResultType.RelevantResults))

{

ResultTable relevantResultsTable = searchResults[ResultType.RelevantResults];

relevantResults.Load(relevantResultsTable, LoadOption.OverwriteChanges);

}

if (relevantResults != null && relevantResults.Rows.Count > 0)

{

DataView dv = relevantResults.DefaultView;

DataTable dtOrdered = dv.ToTable();

}

}

When I ran the above code I got the results as below.

CustomResults

Thanks to Mikael Svenson for the guidance through email.

Both Part1 and Part 2 are available as document in the below location.

Part1: https://gallery.technet.microsoft.com/SharePoint-2010-Creating-e439cee3

Part2: https://gallery.technet.microsoft.com/SharePoint-2010-Custom-b6ca6b3e

Older Posts »

Categories

Follow

Get every new post delivered to your Inbox.

Join 40 other followers