Home > Blog > How To Investigate SharePoint PnP-JS Issues

In this post, we are going to investigate the Pnp-js library from the SharePoint Patterns and Practices group by building a simple list viewer. We will continue to build on this simple application as we tackle more and more of the PnP-JS library functionality. In this initial post we will look at configuring the library and building a simple application that will display all the lists and libraries as well as their fields.

PnP-JS is a really cool library built on top of the SharePoint rest API. It simplifies writing JavaScript to query the SharePoint REST API and allows us to focus on getting the data we need without having to manage all the ajax requests ourselves.


To keep things simple, we are going to keep all of our code in two files. One file is going to be the base for our HTML and will be placed in a Script Editor Web Part. The other will be our script file and will handle the configuration of PnP-JS and our custom code.
First things first download the latest release of the PnP-JS library from the following URL https://github.com/SharePoint/PnP-JS-Core and jQuery from https://jquery.com/. Go ahead and upload both files to your Site Assets library.

Next, create a new JavaScript file and call it pnp-test.js, this will be where we write all our code. Start this file off with a simple self-executing function.

(function() {

Now we can set up and configure the PnP-JS library. Inside the self-executing function place the following configuration code. Without this configuration the library will not function correctly. This will set up our Accept header for the rest calls and force JSON to be returned instead of XML.

sp: {
headers: {
“Accept”: “application/json;odata=verbose”

Now that the PnP-JS configuration is done we can start utilizing the library to query SharePoint.

Setup Page and ScriptEditor

Let’s got to our Site Pages and add a new page to test out our script. We then need to add a script editor web part and add the following content to scaffold our HTML and get our scripts imported into the page. Go ahead and update the script links below to reflect where you scripts are.

Query Lists

Querying lists is very simple with the Pnp-js library. It supports OData operators such as top, select, filter, orderby and skip. Let’s look at a simple query to get all the lists in the site and order them by title. $pnp.sp.web.lists.orderBy(‘Title’).get().then(function(data) { }); Here we start our query off with $pnp.sp.web.lists, this starts the query to get all of the lists in the site. Next is the .orderBy operator this tells the rest API to order the query results by the given field. In this case the Title field. The .get() command finishes off our query and executes it. We can then process the data in the then function. It’s worth noting here that in addition to the then function a catch function is also supported to handle any errors encountered executing the query. We can add the following code to the then function to process our data and display it on the page. $(data).each(function(index, item) { $(‘#lists’).append(‘
  • ‘ + item.Title + ‘
  • ‘) }); This code enumerates the returned lists and creates a new list item and link to display each list in and appends it to our list UL in the preceding markup. Here we just store the list id in the data-id element and add the title to display. This will facilitate calling a click event on each list so we can process each item when clicked.

    Query Fields

    Next, let’s look at querying fields and wiring up the click event for the items we just added to the unordered list. We will use jQuery to hook up the click event on the document then listen for the click event from our list items. We start off by getting the list id so we can query that list for its fields. $(document).on(‘click’, ‘.lst-btn’, function() { var id = $(this).data(‘id’); }); We then add some code to get some basic information from the list, here we are just displaying the title and description on the page. It’s simple enough to get the list by id then display the title and description by utilizing the getById() function. $pnp.sp.web.lists.getById(id).get().then(function(data) { var desc = data.Description; var title = data.Title; $(‘#lst-title’).html(title); $(‘#lst-desc’).html(desc); }); Finally, we can query the list for its fields, order them by title and build up our HTML to display the Title, Type, Internal Name and if the field is required. $(document).on(‘click’, ‘.lst-btn’, function() { var id = $(this).data(‘id’); $(‘#fld’).hide(); $pnp.sp.web.lists.getById(id).get().then(function(data) { var desc = data.Description; var title = data.Title; $(‘#lst-title’).html(title); $(‘#lst-desc’).html(desc); $(‘#lst-flds’).empty(); $pnp.sp.web.lists.getById(id).fields.orderBy(‘Title’).get().then(function(data) { $(data).each(function(index, item) { var title = item.Title; var type = item.TypeAsString; var id = item.Id; var internalName = item.InternalName; var required = item.Required; $(‘#fld’).show(); $(‘#lst-flds’).append(‘
  • Title: ‘ + title +’
    Internal Name: ‘ + internalName +’
    Field Type: ‘ + type +’
  • ‘); }); }); }); }); $pnp.sp.web.lists.orderBy(‘Title’).get().then(function(data) { $(data).each(function(index, item) { $(‘#lists’).append(‘
  • ‘ + item.Title + ‘
  • ‘) }); }); After putting all the code together, we have a nice little app that show’s us all the lists and their fields. The PnP-JS library really simplifies utilizing the SharePoint REST API and lets us concentrate on building applications rather than plumbing ajax calls to an API. Stay tuned in our next installment we will look at adding more features to our list viewer to display views and content types. (function() { $pnp.setup({ sp: { headers: { “Accept”: “application/json; odata=verbose”, }, } }); $(‘#fld’).hide(); $pnp.sp.web.lists.orderBy(‘Title’).get().then(function(data) { $(data).each(function(index, item) { $(‘#lists’).append(‘
  • ‘ + item.Title + ‘
  • ‘) }); }); $(document).on(‘click’, ‘.lst-btn’, function() { var id = $(this).data(‘id’); $(‘#fld’).hide(); $pnp.sp.web.lists.getById(id).get().then(function(data) { var desc = data.Description; var title = data.Title; $(‘#lst-title’).html(title); $(‘#lst-desc’).html(desc); $(‘#lst-flds’).empty(); $pnp.sp.web.lists.getById(id).fields.orderBy(‘Title’).get().then(function(data) { $(data).each(function(index, item) { var title = item.Title; var type = item.TypeAsString; var id = item.Id; var internalName = item.InternalName; var required = item.Required; $(‘#fld’).show(); $(‘#lst-flds’).append(‘
  • Title: ‘ + title +’
    Internal Name: ‘ + internalName +’
    Field Type: ‘ + type +’
  • ‘); }); }); }); }); }());


    [wpforms id="1422"]
    <div class="wpforms-container wpforms-container-full" id="wpforms-1422"><form id="wpforms-form-1422" class="wpforms-validate wpforms-form" data-formid="1422" method="post" enctype="multipart/form-data" action="/blog/investigating-sharepoint-pnp-js" data-token="02a3e52e1f88e4640a52ae3eaf408d12"><noscript class="wpforms-error-noscript">Please enable JavaScript in your browser to complete this form.</noscript><div class="wpforms-field-container"><div id="wpforms-1422-field_0-container" class="wpforms-field wpforms-field-name" data-field-id="0"><label class="wpforms-field-label" for="wpforms-1422-field_0">Full Name <span class="wpforms-required-label">*</span></label><input type="text" id="wpforms-1422-field_0" class="wpforms-field-large wpforms-field-required" name="wpforms[fields][0]" required></div><div id="wpforms-1422-field_1-container" class="wpforms-field wpforms-field-email" data-field-id="1"><label class="wpforms-field-label" for="wpforms-1422-field_1">Email <span class="wpforms-required-label">*</span></label><input type="email" id="wpforms-1422-field_1" class="wpforms-field-large wpforms-field-required" name="wpforms[fields][1]" required></div><div id="wpforms-1422-field_3-container" class="wpforms-field wpforms-field-phone" data-field-id="3"><label class="wpforms-field-label" for="wpforms-1422-field_3">Phone <span class="wpforms-required-label">*</span></label><input type="tel" id="wpforms-1422-field_3" class="wpforms-field-large wpforms-field-required wpforms-masked-input" data-inputmask="&#039;mask&#039;: &#039;(999) 999-9999&#039;" data-rule-us-phone-field="true" data-inputmask-inputmode="tel" name="wpforms[fields][3]" required></div><div id="wpforms-1422-field_2-container" class="wpforms-field wpforms-field-textarea" data-field-id="2"><label class="wpforms-field-label" for="wpforms-1422-field_2">How can we help you? <span class="wpforms-required-label">*</span></label><textarea id="wpforms-1422-field_2" class="wpforms-field-small wpforms-field-required" name="wpforms[fields][2]" required></textarea></div><div id="wpforms-1422-field_15-container" class="wpforms-field wpforms-field-html" data-field-id="15"><div id="wpforms-1422-field_15"><p style="padding-top: 10px; padding-bottom: 10px; font-family: 'Open Sans', sans-serif; font-size: 10px; color: #333333;">By clicking the button below, you are agreeing to our <span style="text-decoration: underline;"><span style="color: #000000;"><a style="color: #000000; text-decoration: underline;" href="https://www.incworx.com/privacy-policy">Privacy Policy</a></span></span>.</p></div></div><div id="wpforms-1422-field_7-container" class="wpforms-field wpforms-field-hidden" data-field-id="7"><input type="hidden" id="wpforms-1422-field_7" name="wpforms[fields][7]" value="How To Investigate SharePoint PnP-JS Issues"></div><div id="wpforms-1422-field_9-container" class="wpforms-field wpforms-field-hidden" data-field-id="9"><input type="hidden" id="wpforms-1422-field_9" name="wpforms[fields][9]" value=""></div><div id="wpforms-1422-field_10-container" class="wpforms-field wpforms-field-hidden" data-field-id="10"><input type="hidden" id="wpforms-1422-field_10" name="wpforms[fields][10]"></div></div><div class="wpforms-field wpforms-field-hp"><label for="wpforms-1422-field-hp" class="wpforms-field-label">Email</label><input type="text" name="wpforms[hp]" id="wpforms-1422-field-hp" class="wpforms-field-medium"></div><div class="wpforms-submit-container" ><input type="hidden" name="wpforms[id]" value="1422"><input type="hidden" name="wpforms[author]" value="2"><input type="hidden" name="wpforms[post_id]" value="617"><button type="submit" name="wpforms[submit]" class="wpforms-submit " id="wpforms-submit-1422" value="wpforms-submit" aria-live="assertive" data-alt-text="Sending..." data-submit-text="Submit">Submit</button></div></form></div> <!-- .wpforms-container -->