Forum Discussion

Alan Trafford's avatar
Alan Trafford
Brass Contributor
Jan 05, 2017
Solved

Using PnP JS Core: How do I get a list of files from the "Pages" folder of an "Enterprise Wiki"

Hi

 

Using PnP JS Core, How would I go about getting a list of files from the "Pages" folder of an "Enterprise Wiki" and then getting the properties associated with each file?

 

Eventually I want to get all the properties associated with each file. In particular I'm interested in Title, ServerRelativePath and ServerRelativeUrl for now.

 

In case it helps, we use an "Enterprise Wiki" with folders. For each folder I want to generate a table of contents. So for a given folder I would want to filter by the url (ServerRelatieUrl?) for only files in that folder.

 

Thanks.

  • Hi Alan,

     

    First, 'Pages' is not a folder, it's a document library.

    You can query a doc lib by multiple available methods in SharePoint REST API and PnP JS Core REST wrapper, like:

     

    // Get by title
    $pnp.sp.web.lists.getByTitle('Pages').items.get().then(function(item) { console.log(item); });

    or

     

    // Get by list url is more preferable way as list renaming won't crash the logic
    $pnp.sp.web.getList(_spPageContextInfo.webServerRelativeUrl + '/Pages').items.get().then(function(item) { console.log(item); });

    or by querying the real folder objects with `GetFolderByServerRelativeUrl` method like:

     

    $pnp.sp.web
    .getFolderByServerRelativeUrl(_spPageContextInfo.webServerRelativeUrl + '/Pages') // Here comes a folder/subfolder path .files .expand('Files/ListItemAllFields') // For Metadata extraction .select('Title,Name') // Fields to retrieve .get().then(function(item) { console.log(item); });

     

    Cheers

8 Replies

  • Hi Alan,

     

    First, 'Pages' is not a folder, it's a document library.

    You can query a doc lib by multiple available methods in SharePoint REST API and PnP JS Core REST wrapper, like:

     

    // Get by title
    $pnp.sp.web.lists.getByTitle('Pages').items.get().then(function(item) { console.log(item); });

    or

     

    // Get by list url is more preferable way as list renaming won't crash the logic
    $pnp.sp.web.getList(_spPageContextInfo.webServerRelativeUrl + '/Pages').items.get().then(function(item) { console.log(item); });

    or by querying the real folder objects with `GetFolderByServerRelativeUrl` method like:

     

    $pnp.sp.web
    .getFolderByServerRelativeUrl(_spPageContextInfo.webServerRelativeUrl + '/Pages') // Here comes a folder/subfolder path .files .expand('Files/ListItemAllFields') // For Metadata extraction .select('Title,Name') // Fields to retrieve .get().then(function(item) { console.log(item); });

     

    Cheers

    • Alan Trafford's avatar
      Alan Trafford
      Brass Contributor

      Andrew Koltyakov, thanks for the reply.

       

      After some investigation I figured out that 'Pages' was a list and not a folder.

       

      In our "Enterprise Wiki" we have used folders to create a hierarchy. Your last code snippet worked great for getting a list of files, but did not return folders. I modified it slightly (replaced .files with .folders) and was able to get folder information. So it now looks like this:

       

       

      var files;
      $pnp.sp.web
         .getFolderByServerRelativeUrl(_spPageContextInfo.webServerRelativeUrl + '/Pages') // Here comes a folder/subfolder path
         .files
         .expand('Files/ListItemAllFields') // For Metadata extraction
         .select('Title,Name')              // Fields to retrieve
         .get()
      .then(function(item) { files = item; }); var folders; $pnp.sp.web .getFolderByServerRelativeUrl(_spPageContextInfo.webServerRelativeUrl + '/Pages') // Here comes a folder/subfolder path .files .expand('Folders/ListItemAllFields') // For Metadata extraction .select('Title,Name') // Fields to retrieve .get()
      .then(function(item) { folders = item; });

      Is this OK or is there a better way?

       

      Thanks.

       

      • Andrew Koltyakov's avatar
        Andrew Koltyakov
        MVP

        Hi Alan Trafford,

         

        There could be at least 2 strategies with your case:

         

        1. When a number of articles (with folders) is relatively small (less than 5000) - it's possible to use one single query for getting all the structure you have in a document library recursively then with the use of FileDirRef build your custom navigation UI;
        2. When a number of the wiki pages is unpredictably large, then an on-demand query per folder's files and folders during a category (folder) drill down UI interaction.

        In case of the first scenario, I would recommend using `$pnp.sp.web.getList(_spPageContextInfo.webServerRelativeUrl + '/Pages').items` ... with the conditions and so on.

         

        With the second one, imo, it's better to deal with `$pnp.sp.web.getFolderByServerRelativeUrl('[...path to folder...]').files` and `$pnp.sp.web.getFolderByServerRelativeUrl('[...path to folder...]').folders` in a batch request. Or using plain REST call `/_api/Web/GetFolderByServerRelativeUrl(@FolderServerRelativeUrl)?$expand=Folders,Files,Folders/ListItemAllFields,Files/ListItemAllFields$select=...`.

         

        Using search API also can be a good idea. A lot depends on usage scenarios and data amount.

        For instance, I would decide to show only categories structure in the wiki menu. In the case of folders, it can be easily one single cached request to a list's folders. In some more advanced cases you would need to apply multiple categories to the wiki article, then managed metadata is better (with MMD you can even use OOTB tree MMD navigation).

  • Anonymous's avatar
    Anonymous
    Would you not just use csom for that in combination with JS Core?
    • Alan Trafford's avatar
      Alan Trafford
      Brass Contributor

      Deleted, thanks for the reply.

       

      If possible, I really want to do this in JavaScript. As you say, I could create an add-in and have that do the work. I'm new to SharePoint development it looks like the JavaScript way is simpler, in that I don't have to host it externally.

       

      Also, if this was successful, a follow on project would be to create an enhanced left hand menu. It seems that the easiest way to do this, without creating/editing templates or page layouts, is with JavaScript embedding.

       

      I'm using the judgement, feel free to correct me, that add-ins are for users to add to pages they create. Whereas, JavaScript embedding can be used to make changes to all pages.

       

      BTW I never used Azure, have beginners skills in JavaScript, average skills in C#. I've spent most of the last 5 years or so doing PowerShell and Transact-SQL. I have good skills on both of these.

Resources