SharePoint Framework Client Side Web Part accessing Data from External API

This guide will help you setup a local SharePoint work environment (Workbench).
You will also build your first web part and populate it using an external API.

Setting up the Windows development environment

1) Install cmder (console emulator) http://cmder.net/
2) Install Node.js https://nodejs.org/en/ (Install the LTS version)
3) Start cmder and download all the .js files by issuing the following commands:
npm install -g npm (-g = Global)
npm install -g yo (Installs Yeoman)
npm install -g gulp (Installs Gulp)
npm install -g @microsoft/generator-sharepoint (SharePoint Generator)
5) Run vscode and install the following extension: “React Extension Pack
Extensions incuded in React Extension Pack
Reactjs code snippets – Adds code snippets for React development in ES6
ES Lint – Integrates ESLint into VS Code.
npm – Run npm scripts from the command palatte and validate the installed modules defined in package.json.
JavaScript (ES6) Snippets – Adds code snippets for JavaScript development in ES6 syntax.
Search node_modules – Quickly search for node modules in your project.
NPM IntelliSense – Adds IntelliSense for npm modules in your code.
Path IntelliSense – Autocompletes filenames in your code.
6) Install the “yo” (Yeoman) extension.
7) Install the “Debugger for Chrome” extension.

Create your first project

1) Okay, lets create a project now. See image below for commands or issue the commands below.
NOTE: If you get an error when running the “yo @microsoft/sharepoint” command below, set your execution policy with “Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass” then run the command again.
  • cd \Projects
  • md staff
  • cd staff
  • yo @microsoft/sharepoint
  • Press Enter to accept default (staff)
  • Press Enter to accept default (SharePoint Online only (latest))
  • Press Enter to accept default (Use the current folder)
  • Enter N to the next 2 questions
  • Press Enter to accept default (WebPart)
  • Press Enter to accept default Web part name (staff)
  • Enter a description for your Web part
  • Press Enter to accept default (No JavaScript framework)

sharepoint create new project

2) It will take a few minutes to create the project, once it finishes you should see a completion message like below.
sharepoint create project confirmation
3) Let’s make sure everything is working. Run the “gulp serve” command to build the Workbench, when it finishes you should see the following page in your browser. If you get a blank screen try refreshing the page.
NOTE: If you get an error when running the “gulp serve” command below, set your execution policy with “Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
sharepoint project select web part
4) If your workbench loaded, go ahead and close your browser.
5) Go back to vscode. Currently the Workbench is running in the background, if you want to stop it issue the CTRL-C command. But you will have to issue the “gulp serve” command again before debugging.
6) Inside vscode open your staff project folder (or whatever you named your project).
7) Drill down to \src\webparts\staff and click on the StaffWebParts.ts file. You should see something similar to the image below.
sharepoint edit project files

 

8) Right click on the “loc” folder and select “New File” and name it “requests.ts“. Then copy the code below and paste it into that file. Save the file.
/**
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * Found on github: https://gist.github.com/codecorsair
 */
export interface RequestOptions {
  ignoreCache?: boolean;
  headers?: {[key: string]:string};
  // 0 (or negative) to wait forever
  timeout?: number;
}

export const DEFAULT_REQUEST_OPTIONS = {
  ignoreCache: false,
  headers: {
    Accept: 'application/json, text/javascript, text/plain',
  },
  // default max duration for a request
  timeout: 5000,
};

export interface RequestResult {
  ok: boolean;
  status: number;
  statusText: string;
  data: string;
  json: <T>() => T;
  headers: string;
}

function queryParams(params: any = {}) {
  return Object.keys(params)
      .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
      .join('&');
}

function withQuery(url: string, params: any = {}) {
  const queryString = queryParams(params);
  return queryString ? url + (url.indexOf('?') === -1 ? '?' : '&') + queryString : url;
}

function parseXHRResult(xhr: XMLHttpRequest): RequestResult {
  return {
    ok: xhr.status >= 200 && xhr.status < 300,
    status: xhr.status,
    statusText: xhr.statusText,
    headers: xhr.getAllResponseHeaders(),
    data: xhr.responseText,
    json: <T>() => JSON.parse(xhr.responseText) as T,
  };
}

function errorResponse(xhr: XMLHttpRequest, message: string | null = null): RequestResult {
  return {
    ok: false,
    status: xhr.status,
    statusText: xhr.statusText,
    headers: xhr.getAllResponseHeaders(),
    data: message || xhr.statusText,
    json: <T>() => JSON.parse(message || xhr.statusText) as T,
  };
}

export function request(method: 'get' | 'post',
  url: string,
  queryParams: any = {},
  body: any = null,
  options: RequestOptions = DEFAULT_REQUEST_OPTIONS) {
  
  const ignoreCache = options.ignoreCache || DEFAULT_REQUEST_OPTIONS.ignoreCache;
  const headers = options.headers || DEFAULT_REQUEST_OPTIONS.headers;
  const timeout = options.timeout || DEFAULT_REQUEST_OPTIONS.timeout;

  return new Promise<RequestResult>((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open(method, withQuery(url, queryParams));
  
    if (headers) {
      Object.keys(headers).forEach(key => xhr.setRequestHeader(key, headers[key]));
    }

    if (ignoreCache) {
      xhr.setRequestHeader('Cache-Control', 'no-cache');
    }

    xhr.timeout = timeout;

    xhr.onload = evt => {
      resolve(parseXHRResult(xhr));
    };

    xhr.onerror = evt => {
      resolve(errorResponse(xhr, 'Failed to make request.'));
    };

    xhr.ontimeout = evt => {
      resolve(errorResponse(xhr, 'Request took longer than expected.'));
    };

    if (method === 'post' && body) {
      xhr.setRequestHeader('Content-Type', 'application/json');
      xhr.send(JSON.stringify(body));
    } else {
      xhr.send();
    }
  });
}
9) Change back to the “StaffWebParts.ts” file.
10) Add the following block of code just inside the “public render(): void {” section.
    //Begin: Call the api and populate the EmployeeList div.
    { 
      request("get", "https://jsonplaceholder.typicode.com/users")
      .then(function(data) {

        interface MyObj {
          name: string;
          email: string;
      }

        var Html = ""; 
        let obj: MyObj = JSON.parse(data.data);
        console.log(obj);
                         
        for (var i in obj) {
            Html += "<div>Name: "+ obj[i].name + ", Email: " + obj[i].email +"</div>";                   
        }
        document.getElementById('EmployeeList').innerHTML = Html;
      })
      .catch(function(error){
        console.log('Something went wrong!',error);
      })            
    } 
    //End: Call the api and populate the EmployeeList div.
11) Then add the following import reference in the top section of the page.
import { request } from './loc/requests';
12) Then modify the “this.domElement.innerHTML” section to look like the code below.
    this.domElement.innerHTML = `
      <div class="${ styles.staff }">
        <div class="${ styles.container }">
          <div class="${ styles.row }">
            <div class="${ styles.column }">
              <div class="${ styles.label }">Staff Members</div>          
                <div id="EmployeeList" class="${ styles.row }"></div>
            </div>
          </div>
        </div>
      </div>`;     
13) Alright, lets see if it works. Fire up the WorkBench if it isn’t already running with “gulp serve“.
14) In the SharePoint Workbench add the staff Web Part.
sharepoint insert web part
15) If everything went smooth, you should see the following results after adding the Web Part.
NOTE: If you don’t see any results, try closing the browser, then run the debugger “F5“. The debugger should run in Chrome. Edge had problems pulling results for some reason.
sharepoint web part view