SharePoint Online Add-In with CRUD operations using DefinitelyTypedJquery, TypeScript and REST API – Part 1

Pankaj Salunkhe

Pankaj Salunkhe

Technical Specialist at CG
Microsoft Certified Solution expert in SharePoint and O365 with 9+ years of experience.

write to admin@sharecareinspire.com for contribution
Pankaj Salunkhe

Latest posts by Pankaj Salunkhe (see all)

>> Part 2      Related Articles      Download code

Introduction

In this article i am covering how to create a SharePoint Add-In with Typescript, DefinitelyTypedJquery and REST API.

Before diving deep into the SharePoint Add-In development you need to understand few concepts related to SharePoint Add-In.

SharePoint Add-In

SharePoint Add-ins are self-contained extensions of SharePoint websites that you create, and that run without custom code on the SharePoint server.

There are two types of SharePoint Add-ins, SharePoint-hosted & Provider-hosted.

 

Microsoft has changed the name “Apps for SharePoint” to “SharePoint Add-Ins”,  these add-ins fit seamlessly into the SharePoint website page where they are added. Add-ins can have three possible type of shapes as shown below.

Immersive: Immersive add-in takes entire browser experience.
App Part: This add-in is nothing but a type of Web Part.
Custom Actions: This app type is useful to create new actions for documents or list items.

SharePoint-hosted SharePoint Add-ins

SharePoint hosted add-in is centered around SharePoint components like lists, pages, web parts, workflows, libraries, and more.

Business logic of this type of add-in is in JavaScript on custom SharePoint pages.

Typescript

Typescript has been around for several years now trying to gain traction in the web development community. For those who are unfamiliar with Typescript, please refer articles related to SPFx here .

Definitely Typed

The DefinitelyTyped JQuery adds definitions for the existing many JavaScript libraries in the form of interfaces.

These files describes the types defined in the external libraries (d.ts), files are deployed and only used for development purpose to check the types.

Create SharePoint Add-In and provide TypeScript support 

As we have now understood about SharePoint Add-Ins and TypeScript, let us now see how can create SharePoint Add-In and use TypeScript in it.

Step 1: Create a new SharePoint-hosted app in Visual Studio 2017.

Visual Studio 2017 has inbuilt template project template for SharePoint Add-Ins, if you are using any other version make sure you install required templates.

Step 2: Add TypeScript File

Once project is created, delete the default app.js file. Add new TypeScript file named app.ts in “Scripts” folder.

Step 3: Add Nuget Package

Now you need to add Definitely Typed JQuery  package to project. In Solution Explorer, right-click the project and select Manage NuGet Packages from the context menu and add following packages.

You need to add following two packages.

JQuery.Typescript.Definitelytyped

SharePoint.Typescript.DefinitelyTyped

Step 4: Refer TypeScript files in project

In standard Visual Studio web projects, typing’s are automatically referenced. In a SharePoint project, however, you must add the references directly to the TS file using the triple whack syntax at the top of the App.ts file.

/// <reference path=”typings/SharePoint/SharePoint.d.ts”/>
/// <reference path=”typings/jQuery/jquery.d.ts”/>

Step 5: Include App.js and App.js.map file in Project

Now you can build the project, which will create an associated App.js and App.js.map file in the project. However, you will not see the file in the Solution Explorer until you add it manually.

In the Solution Explorer, click Show All Files. Locate the hidden App.js and App.js.map file, and Include in Project.

Coding SharePoint app – Step by Step

Now that the TypeScript support is all in place, you can begin coding the functionality. This example will make use of types, module, interface, and class to create the required functionality.

A TypeScript module is a container for organizing code and is closely related to the JavaScript concept of a module or a namespace.

Step 1: Create SharePoint list

Create list with fields firstname, lastname, address in host site collection with name HostList

Step 2: Create Default.aspx

Add below code in Default.aspx page, i have created the very basic Page to capture the user information such as First Name, Last Name and Address.

File: Default.aspx

<%-- The following 4 lines are ASP.NET directives needed when using SharePoint components --%>
<%@ Page Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" MasterPageFile="~masterurl/default.master" Language="C#" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%-- The markup and script in the following Content element will be placed in the <head> of the page --%>
<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
    <link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
    <script type="text/javascript" src="../Scripts/jquery-1.9.1.min.js"></script>
      <script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
    <SharePoint:ScriptLink  name="sp.runtime.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" />
    <SharePoint:ScriptLink name="sp.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" />
    <meta name="WebPartPageExpansion" content="full" />
    <!-- Add your CSS styles to the following file -->
    <link rel="Stylesheet" type="text/css" href="../Content/App.css" />
    <!-- Add your JavaScript to the following file -->
    <script type="text/javascript" src="../Scripts/App.js"></script>
</asp:Content>
<%-- The markup in the following Content element will be placed in the TitleArea of the page --%>
<asp:Content ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
    Page Title
</asp:Content>
<%-- The markup and script in the following Content element will be placed in the <body> of the page --%>
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
    <%--<div>
        <p id="message">
             The following content will be replaced with the user name when you run the app - see App.js
            initializing...
        </p>
    </div>--%>
    <input type="button" value="New Item" id="Button1" onclick="App.Config.ShowDialogNewItem()" />
<input type="button" value="Get All Items" id="btnAll" onclick="App.Config.getItems()" />
    <table id="addtable" class="gridtable"></table>
    <div id="newRecordPanel" style="display:none">
    <table>
    <tr><td><span id="itemId"></span></td></tr>
         <tr>
             <td> Name</td>
             <td><input type="text" id="txtFirstNameNew"  placeholder="First Name" size="20"/></td>
               </tr>
        <tr>
            <td>Last Name</td>
            <td><input type="text" size="20" id="txtLastNameNew"  placeholder="Last Name"/></td>
        </tr>
        <tr>
            <td>Address</td>
            <td><input type="text" size="20" id="txtAddressNew"  placeholder="Address"/></td>
        </tr>
         <tr>
             <td><input type="button" id="btnEdit" value="Save" onclick="App.Config.addListItem()" /></td>
         </tr>
          </table>
        </div>
    <div id="dialog" class="ui-dialog" style="display:none">
    <table>
    <tr><td><span id="itemEdit"></span></td></tr>
        <tr>
   <td> Name</td><td><input type="text" id="txtEditFirstName" required placeholder="First Name" size="20"/></td>
               </tr>
    <tr><td>Last Name</td><td><input type="text" size="20" id="txtEditLastName" required placeholder="Last Name"/></td> </tr>
    <tr><td>Address</td><td><input type="text" size="20" id="txtEditAddress" required placeholder="Address"/></td> </tr>
        <tr><td><input type="button" id="Button2" value="Update" onclick="App.Config.ItemUpdate()" /></td></tr>
        </table>
        </div>
     <div id="deleteItemDiv" class="ui-dialog"  style="display:none">
        <p>Do you want to delete the item</p>  
    </div>
     <div id="statusPane" class="ui-dialog" style="display:none">
      <p>Record Addedd Successfuly</p>
    </div>
</asp:Content>

Step 3: Create App.ts

Add below code in App.ts file, this file implements all the methods of CRUD operations on SharePoint list using Typescript, DefinitelyTypedJQuery, REST APIs

File: App.ts

/// <reference path="typings/SharePoint/SharePoint.d.ts"/>
/// <reference path="typings/jQuery/jquery.d.ts"/>
module App {
    export class Config {
        // read URL parameters
        private static manageQueryStringParameter(paramToRetrieve: string): any {
            var params =
                document.URL.split("?")[1].split("&");
            var strParams = "";
            for (var i = 0; i < params.length; i = i + 1) {
                var singleParam = params[i].split("=");
                if (singleParam[0] == paramToRetrieve)
                    return singleParam[1];
            }
        }
        public static appWebUrl: string;
        public static hostUrl: string;
        public static blogsHTML: string = "";
        public static url: string = "";
        //open the dialog on new item button click
        public static ShowDialogNewItem() {
            jQuery("#txtFirstNameNew").val("");
            jQuery("#txtLastNameNew").val("");
            jQuery("#txtAddressNew").val("");
            jQuery("#newRecordPanel").dialog();
        }

       // include Add item method
       // include update item method
       // include read all and delete item method

       // get the URL and load the items on the page
        public static loadConfig(): void {
            Config.appWebUrl = decodeURIComponent(this.manageQueryStringParameter("SPAppWebUrl"));
            Config.hostUrl = decodeURIComponent(this.manageQueryStringParameter("SPHostUrl"));
            Config.getItems();
        }
    }

    App.Config.loadConfig();
}

Add addListItem method in App.ts file

        // create the item in the list
        public static addListItem() {
            var fname: string = jQuery("#txtFirstNameNew").val();
            var lname: string = jQuery("#txtLastNameNew").val();
            var address: string = jQuery("#txtAddressNew").val();
            App.Config.url = App.Config.appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle('HostList')/items?@target='" + App.Config.hostUrl + "'";
            return jQuery.ajax({
                method: 'POST',
                url: App.Config.url,
                data: JSON.stringify
                    ({
                        __metadata:
                        {
                            type: "SP.Data.HostListListItem"
                        },
                        Title: fname,
                        LastName: lname,
                        Address: address
                    }),
                headers: {
                    "Accept": "application/json;odata=verbose",
                    "Content-Type": "application/json;odata=verbose",
                    "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
                    "X-HTTP-Method": "POST" },
                success: (data: any, status: string, jqXHR: JQueryXHR) => { 
                    App.Config.getItems();
                    alert("Successfully Added");
                    jQuery("#newRecordPanel").dialog("close");
                },
                error: (jqXHR: JQueryXHR, status: string, error: string) => {
                    alert("Error on Adding:" + error);
                }
            });
        }

Add ItemUpdate method in App.ts file

        //update the item in the list
        public static ItemUpdate() {         
            var iteId: string = jQuery("#itemEdit").html();
            var fname: string = jQuery("#txtEditFirstName").val();
            var lname: string = jQuery("#txtEditLastName").val();
            var address: string = jQuery("#txtEditAddress").val();
            App.Config.url = App.Config.appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle('HostList')/items(" + iteId + ")?@target='" + App.Config.hostUrl + "'";
            console.log(App.Config.hostUrl);
            console.log(App.Config.url);
            return jQuery.ajax({
                method: 'PATCH',
                url: App.Config.url,
                data: JSON.stringify
                    ({
                        __metadata:
                        {
                            type: "SP.Data.HostListListItem"
                        },
                        Title: fname,
                        LastName: lname,
                        Address: address
                    }),
                headers: {
                    "Accept": "application/json;odata=verbose",
                    "Content-Type": "application/json;odata=verbose",
                    "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
                    "X-Http-Method": "PATCH",
                    "If-Match": "*"
                },
                success: (data: any, status: string, jqXHR: JQueryXHR) => {                  
                    App.Config.getItems();
                    alert("Successfully updated");
                    jQuery("#dialog").dialog("close");
                },
                error: (jqXHR: JQueryXHR, status: string, error: string) => {
                    alert("Error on Updating:" + error);
                }
            });
        }

Add getItems method and Delete code in App.ts

        //read the Items from the list
        public static getItems() {
            App.Config.url = App.Config.appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle('HostList')/items?@target='" + App.Config.hostUrl + "'";
            console.log(App.Config.hostUrl);
            console.log(App.Config.url);
            return jQuery.ajax({
                method: 'GET',
                url: App.Config.url,
                headers: { "Accept": "application/json; odata=verbose" },
                success: (data: any, status: string, jqXHR: JQueryXHR) => {
                    console.log(data);
                    console.log("Method called");
                    var tableRow: string = "<table class='gridtable'><th>ID</th><th>First Name</th><th>Last Name</th><th>Address</th>";
                    for (var i: number = 0; i < data.d.results.length; i++) {
                        tableRow = tableRow + '<tr>' +
                            '<td>' + data.d.results[i].ID + '</td>' +
                            '<td>' + data.d.results[i].Title + '</td>' +
                            '<td>' + data.d.results[i].LastName + '</td>' +
                            '<td>' + data.d.results[i].Address + '</td>' +
                            '<td class="paramUpdate"> <a id="lnkEdit">Edit</a></td>' +
                            '<td><a id="lnkDelete">Delete</a></td>' +
                          '</tr>';
                    }
                    tableRow += '</table>';
                    jQuery("#addtable").html(tableRow);
                    jQuery("#addtable").css({
                        "border-color": "#C1E0FF",
                        "border-width": "1px",
                        "border-style": "solid"
                    });
                    jQuery('#addtable td:nth-child(6)').bind('click', function () {
                     var iteId: string = jQuery(this).closest("tr").children().eq(0).html();
                     jQuery("#deleteItemDiv").dialog({
                            modal: true, title: 'Delete Confirmation', width: 400, buttons: {
                                "Ok":
                                //delete the item from the list 
                                function DeleteItem(itemId:string) {
                                    itemId = iteId;
                                    App.Config.url = App.Config.appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle('HostList')/items(" + itemId + ")?@target='" + App.Config.hostUrl + "'";
                                    return jQuery.ajax({
                                        method: 'POST',
                                        url: App.Config.url,
                                        headers: {
                                            "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
                                            "IF-MATCH": "*",
                                            "X-HTTP-Method": "DELETE"
                                        },
                                        success: (data: any, status: string, jqXHR: JQueryXHR) => {
                                            App.Config.getItems();
                                            jQuery(this).dialog("close");
                                        },
                                        error: (jqXHR: JQueryXHR, status: string, error: string) => {
                                            alert("Error on fetching:" + error);
                                        }
                                    });
                                }
                                , "Cancel": function () {
                                    jQuery(this).dialog("close");
                                }
                            }
                        });
                    });
                    jQuery('#addtable td:nth-child(5)').bind('click', function () {
                        jQuery("#dialog").dialog();
                        var iteId: string = jQuery(this).closest("tr").children().eq(0).html();
                        var fname: string = jQuery(this).closest("tr").children().eq(1).html();
                        var lname: string = jQuery(this).closest("tr").children().eq(2).html();
                        var address: string = jQuery(this).closest("tr").children().eq(3).html();
                        jQuery("#txtEditFirstName").val(fname);
                        jQuery("#txtEditLastName").val(lname);
                        jQuery("#txtEditAddress").val(address);
                        jQuery("#itemEdit").html(iteId);
                    });
                },
                error: function (jqXHR: JQueryXHR, status: string, error: string) {
                    alert("Error on fetching:" + error);
                }
            });
        }

Step 3: Set Permission in AppManifest

Now set appropriate app permissions in the app manifest for Add-In,  in solution explorer double click on AppManifest.xml and click Permissions tab where you have to select scope as Web and Permission as Write.

We are done with the configuration and coding part now.

Next article will focus on build and deployment steps.

>> Part 2      Related Articles     Download code


Check Articles From Categories      Health and Parenting      Inspiring Stories      Technology      Microsoft Azure      SharePoint O365

Leave a Reply

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