April 10, 2019

How to Create Single Page Application in SharePoint – Part 3

685 Views
How to Create Single Page Application in SharePoint – Part 3

Simple SharePoint SPA with Example

So far, we have looked at the introduction in Part 1 and getting started in Part 2.

In this part of this article series we will go through the steps below,

  • Create SPA layout using CSS Grid
  • Create a simple React component which fetch all the lists from the SharePoint site within the selected context and will arrange them in the Left Navigation section.
  • Click on the list name will display the records with title and IDs in a main section

Create SPA layout using CSS Grid

A Single Page Applications will typically consists of five sections as stated i.e. Header, LeftNavigation, Main Content,Right Navigation and then the footer. The challenge always has been to create a responsive layout. Fortunately, there are plenty of options available now. In this example, I am using the CSS grid .

In the IDE open the file App.css file and then replace the existing content with the CSS mark up as mentioned in the snippet below.


	.header { grid-area: header; }    
	.leftnav { grid-area: menu; }    
	.main { grid-area: main; }    
	.rightnav { grid-area: right; }    
	.footer { grid-area: footer; }    
	    
	.grid-container {    
	  display: grid;    
	  grid-template-areas:    
	    'header header header header header header'    
	    'menu main main main main right'    
	    'menu footer footer footer footer footer';    
	  grid-template-columns: 200px 1fr 1fr 1fr 200px;    
	  grid-template-rows:  50px 1fr auto;    
	  grid-gap: 10px;    
	  background-color: #2196F3;    
	  padding: 10px;    
	  min-height: 100vh;    
	}    
	    
	.grid-container > div {    
	  background-color: rgba(255, 255, 255, 0.8);    
	  text-align: center;    
	  padding: 20px 0;    
	  font-size: 20px;    
	}    

Note

Explanation about how this works is out of scope of this article, please refer to some of the CSS grid training materials

Now, the next step is to make the adjustment in the App component. To do this, open the App.tsx file and then replace the existing content with the below code snippet.


	import * as React from 'react';  
	import './App.css';  
	import {  
	    Web  
	} from '@pnp/sp';  
	
	const web = new Web("https://yourtenant.sharepoint.com/sites/dev/");
	  
	class App extends React.Component < any, any > {  
	    constructor(props: any) {  
	        super(props);  
	        this.state = {  
	            lists: [],  
	            listItems: []  
	        };  
	        this._onClickHandler = this._onClickHandler.bind(this);  
	    }  
	    async _onClickHandler(e: React.MouseEvent < HTMLElement > ) {  
	        var listName = e.currentTarget.innerText;  
	        var lstResults = [{}];  
	        const result = await web.lists.getByTitle(listName).items.get();  
	        for (var i = 0; i < result.length; i++) {  
	            lstResults.push({  
	                key: i,  
	                ID: result[i].Id,  
	                Title: result[i].Title  
	            })  
	        }  
	        this.setState({  
	            listItems: lstResults  
	        });  
	    }  
	    componentWillMount() {  
	        const lists: any = [];  
	        web.lists.get().then(Alllists => {  
	            Alllists.forEach(function(list, index) {  
	                lists.push({  
	                    key: index,  
	                    title: list.Title  
	                });  
	            })  
	            this.setState({  
	                lists: lists  
	            })  
	        })  
	    }  
	 public render() {  
	return (  
	  
	        <div className="grid-container">  
	            <div className="header">Header</div>  
	            <div className="leftnav" style={{ textAlign: "left", paddingLeft: "10px" }} >  
	{this.state.lists.map(list =>  
	                <div >  
	                    <a href="#" onClick={this._onClickHandler}>{list.title}</a>  
	                </div>)}  
	  
	            </div>  
	            <div className="main">  
	{(this.state.listItems.length === 0) ? 'No Data' :  
	  
	                <table>  
	                    <tbody>  
	                        <tr>  
	                            <th>Title</th>  
	                            <th>ID</th>  
	                        </tr> {this.state.listItems.map(lstitems =>  
	                        <tr>  
	                            <td> {lstitems.ID} </td>  
	                            <td> {lstitems.Title} </td>  
	                        </tr>)}  
	  
	                    </tbody>  
	                </table>}  
	  
	            </div>  
	            <div className="rightnav">Right</div>  
	            <div className="footer">Footer</div>  
	        </div>  
	);  
	}  
	}  
	export default App;  

Since this is not an article about the React JS or CSS Grid, I will not explain the details about how the code works here. I will be looking forward to comments, if you need any explanation I will be happy to add here. Please note that this example has a very basic setup in terms of CSS and the coding.

Now, after saving both the files you can now run a command "npm start" again and then open the index.aspx file from the SharePoint. Now you should be able to see the page as shown in the image below.

How to Create Single Page Application in SharePoint – Part 3

This is a simple example which sets up the initial template, As you can notice you can click on the name of the any list in the left navigation section and the page will immediately fetch all the records of the selected list and then displays the title and ID in the main section in a tabular format without refreshing the page.

Mentioned below are few of the noticeable references while preparing this article.

There is also a GitHub repository created by me, sp-spa-starter which you can clone or download and use it as a starter for your project.

Issues

You may experience few issues when you follow the steps above. Please perform below mentioned adjustment to couple of files before hitting npm start command.

open the tslint.js file from the root folder and then make adjustment as shown below:


	{  
	  "extends": [],  
	  "defaultSeverity": "warning",  
	  "linterOptions": {  
	    "exclude": [  
	      "config/**/*.js",  
	      "node_modules/**/*.ts",  
	      "coverage/lcov-report/*.js"  
	    ]  
	  }  
	}  

Open the tsconfig.json file under root folder and then add below line under the compiler option


"skipLibCheck": true  

I have also created a GitHub repository with this starter code, you can download or clone this starter kit from here and follow the instructions provided there to execute the project.

One Reply to “How to Create Single Page Application in SharePoint – Part 3”

  1. I’m interested if you plan to continue this series. There are some questions/issues that I have been trying to figure out best practices for when writing SPA’s in SharePoint/Office365.

    1. How do you plan to deploy these apps? Right now you are using a bundle from your local host. This wouldn’t work in a production environment. Normally apps have folders and multiple modules and aren’t bundled in one js file.
    2. How do you handle routing? If you have a number of pages (screens) in your app, how do you handle the fact that you user might press the back button to go to a previous screen? My biggest problem is extending the included navigation in a SharePoint site. It would be nice to add to the default navigation or somehow intercept a back button click.
    3. This is for a classic page. Do you have any idea how it works in a modern page?

Leave a Reply

Your email address will not be published. Required fields are marked *