Thursday 5 March 2020

SPFX - List View webpart using pnp List view control



SPFX webpart using PnP List view control

I have recently came across with an requirement to display pending tasks on modern page from different site/subsites within site collection, There is no way as of now to display on modern page apart from highlight webpart.

I decided to try SPFX and it worked pretty well, tried to made it configurable with options like filter, grouping etc.

SPFX webpart to display list data from single/multiple lists using REST API.Easy to configure and re-use
Using PnP list view webpart to reder data with configurable option to search and filter. Webpart can be configured with set to defined filters/views/groups etc.
This webpart can be used to display pending tasks from single task list or from multiple task lists, it can be used to display documents or list items from any site/subsite.
Screen Shot Below :
Screenshot
Webpart can be configured using below options. Screenshot


I have posted the code on github which can be easily re-used.

https://github.com/agarawalankur/SPFXPnPListViewWebpartSPOnline/blob/master/README.md

Add Attachment is List using spHttpClient in SPFX React webpart

Below code can be used to add attachment in SPFx webpart using spHttpClient or PnP

import { SPHttpClient, SPHttpClientResponse,ISPHttpClientOptions } from '@microsoft/sp-http';

HTML:

<input type="file" name="Attachment" style={{ paddingTop: '5px' }} id="FileAttachment"></input>

JS:

let file = (document.querySelector("#FileAttachment") as HTMLInputElement).files[0];        
          if (file) { 
              let spOpts : ISPHttpClientOptions  = {
                headers: {
                  "Accept": "application/json",
                  "Content-Type": "application/json"
                },
                body: file       
              };
              var url = this.props.siteURL + `/_api/web/lists(guid'` + Taskitem.ParentListID + `')/items` + `('` + Taskitem.ParentItemID + `')` + `/AttachmentFiles/add(FileName='` + file.name +`')`;
              this.props.context.spHttpClient.post(url, SPHttpClient.configurations.v1, spOpts).then((response: SPHttpClientResponse) => {
                console.log(`Status code: ${response.status}`);
                console.log(`Status text: ${response.statusText}`);
                if(Number(`${response.status}`) >300)
                {
                  alert('Error Uploading file, Try again or contact IT');
                  this._closeDialog();
                  return;
                }
                response.json().then((responseJSON: JSON) => {
                  console.log(responseJSON);                 
                });
              });            
          }

        
     
If you want to use pnp then below code can be used:

         var item = sp.web.lists.getById(Taskitem.ParentListID).items.getById(Taskitem.ParentItemID);
             item.attachmentFiles.add(file.name, file).then(v => {
                    //console.log('Check');
             });


Update list id and item id accordingly.

I have tested uploading 10MB files and it uploaded with in couple of seconds.

Happy Coding!

Friday 15 September 2017

Add folder in SharePoint document Library using REST


Below is the function to add folder in document library

My Business Case : I need to attach files in my custom angularjs form, so i used document library to create folder then attach files in that folder.


CreateFolder("TestFolder") ;

function CreateFolder(foldername) {
    //debugger;

    //alert(fileCollectionEndpoint);
    var fileCollectionEndpoint = SiteURL + "/_api/web/getfolderbyserverrelativeurl('MyLibrary')/folders/add(url=\'" + foldername + "\')";
    $.ajax({
        url: fileCollectionEndpoint,
        type: "POST",
        async: false,
        headers: {
            "X-RequestDigest": window.top.$("#__REQUESTDIGEST").val(),
            "accept": "application/json;odata=verbose",
            "content-type": "application/json;odata=verbose"
        },
        success: function(data) {
            //alert('Folder created successfully');
            window.open(AddAttachmentURL + foldername, "_blank")
        },
        error: function(jqXHR, textStatus, errorThrown) {
            //handle error...
            alert(jqXHR.responseText);
        }
    });
}

Get files from SharePoint document library using REST API

Sometimes we need to read files in particular folder in SharePoint, we can achieve this using REST.

My Business Case : I got the requirement in angularjs form to attach documents, so rather than attaching in list item itself, i used document library to attach files and then read it in edit and display form using unique id.

Usage : var filenames = getFolderFiles("foldername");

function getFolderFiles(foldername) {
var attachments = [];
$.ajax({
url: SiteURL + "/_api/web/getfolderbyserverrelativeurl('/SiteCol1/Site1/Library1/" + foldername + "\')/files",
method: "GET",
async: false,
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
var files = data.d.results;
for (i = 0; i < files.length; i++) {
//debugger;
attachments.push(files[i].ServerRelativeUrl);
}
//window.open(AddAttachmentURL + foldername, "_blank")
},
error: function(jqXHR, textStatus, errorThrown) {
//handle error...
alert(jqXHR.responseText);
}
});
return attachments;
}




SharePoint 2013 Client People Picker (Person or Group)

While developing custom forms using HTML/Angularjs we might need people picker controls as well in our HTML.

 Thanks to Microsoft, now in SharePoint we can use client people picker and which you can customize based on your requirement.

Below is the code which we are going to use in our SharePoint page.

I have only used in aspx page which inherits SharePoint master page, i tried in custom aspx page as well but i was not able to implement it.


HTML : 

<div id="ppRMName"></div>

You need below references to initialize it on your page.

<script src="/_layouts/15/clientforms.js"></script> <script src="/_layouts/15/clientpeoplepicker.js"></script>
<script src="/_layouts/15/autofill.js"></script>  
<script src="/_layouts/15/clienttemplates.js"></script>  
<script src="/_layouts/15/sp.js"></script>  
<script src="/_layouts/15/sp.runtime.js"></script>  



Javascript : 

 I used timeout because sometimes it was not loading in browser, you can try calling directly as well.

$(document).ready(function($scope) {
    $("#ppRMName").spPeoplePicker();   
});
$.fn.spPeoplePicker = function() {
    setTimeout(
        function() {          
            ExecuteOrDelayUntilScriptLoaded(function() {
                initializePeoplePicker("ppRMName");
            }, 'sp.core.js');

        }, 500);

}

// function to show people picker control on page, now we need to save and retrieve data as well from People picker
function initializePeoplePicker(peoplePickerElementId) {
// Create a schema to store picker properties, and set the properties.  
var schema = {};
//schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';  
schema['PrincipalAccountType'] = 'User';
//This value specifies where you would want to search for the valid values
schema['SearchPrincipalSource'] = 15;
//This value specifies where you would want to resolve for the valid values
schema['ResolvePrincipalSource'] = 15;
schema['AllowMultipleValues'] = false; // you can define single/multiple here
schema['MaximumEntitySuggestions'] = 50;
schema['Width'] = '300px';
this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, null, schema);
}

// retrieve People picker values

var RMName =  getUserInfo_ppRMName();

function getUserInfo_ppRMName() {
// Get the people picker object from the page.
//ppRMName_TopSpan is the span id which is hard coded
var peoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict.ppRMName_TopSpan;

// Get information about all users.
var userName = getUserInfo(peoplePicker);
return userName;

}

function getUserInfo(peoplePicker) {

var users = peoplePicker.GetAllUserInfo();
var userInfo = '';
var userName = '';
for (var i = 0; i < users.length; i++) {
var user = users[i];
for (var userProperty in user) {
userInfo += userProperty + ':  ' + user[userProperty] + '<br>';
}
}
// Get user keys.
var keys = peoplePicker.GetAllUserKeys();
if (users.length > 0) {
userName = GetSPUserInfo(users[0].Key);

}
return userName;

}

// need spservice reference
function GetSPUserInfo(LoginName) {

var Data = {};
$().SPServices({
operation: "GetUserInfo",
async: false,
userLoginName: LoginName,
completefunc: function(xData, Status) {
$(xData.responseXML).find("User").each(function() {
Data.UserId = $(this).attr("ID");
Data.UserName = $(this).attr("Name");
Data.FullUserName = $(this).attr("ID") + ";#" + $(this).attr("Name");
});
}
});
//return Data;
if (Data.UserId) {
return Data.UserId;
} else {
return AddUsertoGroup(LoginName, "5");
               // if user is new to Sharepoint site, we need to add user to sharepoint to get the user id.
}
}
//This function might ask for authentication pop up, i fixed it using SPservice code to add user

function AddUsertoGroup(userLoginName, GroupID) {
var useridval = "";
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/sitegroups(" + GroupID + ")/users",
type: "POST",
async: false,
contentType: "application/json;odata=verbose",
data: JSON.stringify({
'__metadata': {
'type': 'SP.User'
},
'LoginName': userLoginName
}),
headers: {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: function(data) {
useridval = data.d.Id;
},
error: function(data) {
console.log(data);
}
});
return useridval;
}


Now if you want to set people picker control : PopulatePeoplePicker_ppRMName("UserID");

function PopulatePeoplePicker_ppRMName(UserID) {
var divPeople = SPClientPeoplePicker.SPClientPeoplePickerDict.ppRMName_TopSpan;
var userObj = {
'Key': Value
};
divPeople.AddUnresolvedUser(userObj, true);
}

You want to clear or reset people picker control in some scenarios, below is the function for that.

clearPP("ppRMName_TopSpan");

function clearPP(ppid) {
var spclientPeoplePicker = SPClientPeoplePicker.SPClientPeoplePickerDict[ppid];
if (spclientPeoplePicker) {
//Get the Resolved Users list from Client People Picker
var ResolvedUsers = $(document.getElementById(spclientPeoplePicker.ResolvedListElementId)).find("span[class='sp-peoplepicker-userSpan']");
//Clear the Client People Picker
$(ResolvedUsers).each(function(index) {
spclientPeoplePicker.DeleteProcessedUser(this);
});
}

}


Add user to SharePoint Group using REST API

Rest being powerful api in SharePoint now, we can do most of the operations using REST api, below is the function to add user to SharePoint group.




Usage : AddUsertoGroup("userLoginName", "GroupID");

this function will return the user id, which can be used for further processing.


function AddUsertoGroup(userLoginName, GroupID) {
var useridval = "";
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/sitegroups(" + GroupID + ")/users",
type: "POST",
async: false,
contentType: "application/json;odata=verbose",
data: JSON.stringify({
'__metadata': {
'type': 'SP.User'
},
'LoginName': userLoginName
}),
headers: {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: function(data) {
useridval = data.d.Id;
},
error: function(data) {
console.log(data);
}
});
return useridval;
}

Wednesday 25 January 2017

Sharepoint online management shell--get user cookie

Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
$webUrl = "siteurl"
$username = "ankur@company.com"
$password = Read-Host -Prompt "Password for " -AsSecureString


$cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $username , $password
$onlineCred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username , $password)
$c = $onlineCred.GetAuthenticationCookie($webUrl )


$c

In the end you will get the cookie string if you have proper access.