Here are the steps:

Step 1: SHA Project folder structure.

Step 2: App Web List Creation Steps.

Firstly add simple list into SHA project. Here are the steps to create List into SHA project.

In this example I created custom list named “Customers” as in the following,

Elements.xml File code- it adds data into List.

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  3. <ListInstance Title="Customers" OnQuickLaunch="TRUE" TemplateType="105" FeatureId="00bfea71-7e6d-4186-9ba8-c047ac750105" Url="Lists/Customers" Description="My List Instance">
  4. <Data>
  5. <Rows>
  6. <Row>
  7. <Field Name="FirstName">Rupali</Field>
  8. <Field Name="Title">Shinde</Field>
  9. <Field Name="WorkPhone">(123)456-6789</Field>
  10. </Row>
  11. <Row>
  12. <Field Name="FirstName">Vishnu</Field>
  13. <Field Name="Title">Jadhav</Field>
  14. <Field Name="WorkPhone">(143)867-5309</Field>
  15. </Row>
  16. <Row>
  17. <Field Name="FirstName">DJ</Field>
  18. <Field Name="Title">Jadhav</Field>
  19. <Field Name="WorkPhone">(800)LUV-AZUR</Field>
  20. </Row>
  21. <Row>
  22. <Field Name="FirstName">Summit</Field>
  23. <Field Name="Title">Jadhav</Field>
  24. <Field Name="WorkPhone">(888)123-5677</Field>
  25. </Row>
  26. <Row>
  27. <Field Name="FirstName">Kiran</Field>
  28. <Field Name="Title">Jadhav</Field>
  29. <Field Name="WorkPhone">(888)GOT-OAUTH</Field>
  30. </Row>
  31. <Row>
  32. <Field Name="FirstName">Shrikant</Field>
  33. <Field Name="Title">Shinde</Field>
  34. <Field Name="WorkPhone">(813)813-8133</Field>
  35. </Row>
  36. <Row>
  37. <Field Name="FirstName">Seema</Field>
  38. <Field Name="Title">Jadhav</Field>
  39. <Field Name="WorkPhone">(800)BIG-TULS</Field>
  40. </Row>
  41. </Rows>
  42. </Data>
  43. </ListInstance>
  44. </Elements>

Step 3: User Interface designing steps.

Home page of application is having “Add New Customer “ button, which shows user entry form to fill user details.

User Details Grid – this grid will show user details with Edit, Delete and Display button into it.

  1. <%@ Page Language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  2. <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  3. <%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  4. <%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  5. <asp:Content ID="Content1" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
  6. SharePoint-hosted App REST API Demo
  7. </asp:Content>
  8. <asp:Content ID="Content2" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server">
  9. Using the REST API from Client-side JavaScript
  10. </asp:Content>
  11. <asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
  12. <link rel="Stylesheet" type="text/css" href="../Content/App.css" />
  13. <script type="text/javascript" src="../Scripts/jquery-1.6.2.min.js"></script>
  14. <script type="text/javascript" src="../Scripts/jsrender.js"></script>
  15. <script type="text/javascript" src="../Scripts/App.js"></script>
  16. </asp:Content>
  17. <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
  18. <div id="toolbar">
  19. <input type="button" id="cmdAddNewCustomer" value="Add New Customer" class="ms-ButtonHeightWidth" />
  20. </div>
  21. <div id="results" />
  22. </asp:Content>

Output

Step 4: Grid Data filling steps – the following code is used to fill GridView.

  1. var hostweburl;
  2. var appweburl;
  3. $(function () {
  4. // register event handlers on page
  5. $("#cmdAddNewCustomer").click(onAddCustomer);
  6. $("#results").append($("<img>", { src: "_layouts/images/gears_anv4.gif" }));
  7. // Get the URI decoded URLs.
  8. hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
  9. appweburl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl"));
  10. var scriptbase = hostweburl + "/_layouts/15/";
  11. $.getScript(scriptbase + "SP.RequestExecutor.js", getCustomers);
  12. });
  13. function getCustomers() {
  14. $("#results").empty();
  15. $("<img>", { "src": "/_layouts/images/GEARS_AN.GIF" }).appendTo("#results");
  16. var executor = new SP.RequestExecutor(appweburl);
  17. var FullURL = appweburl + "/_api/web/lists/getbytitle('Customers')/items";
  18. executor.executeAsync(
  19. {
  20. url: FullURL,
  21. method: "GET",
  22. headers: {
  23. "accept": "application/json;odata=verbose",
  24. "content-type": "application/json;odata=verbose",
  25. "X-RequestDigest": $("#__REQUESTDIGEST").val()
  26. },
  27. success: onDataReturned,
  28. error: errorHandler
  29. }
  30. );
  31. }
  32. function errorHandler(data, errorCode, errorMessage) {
  33. document.getElementById("results").innerText = "Could not complete cross-domain call: " + errorMessage;
  34. }
  35. function onDataReturned(data) {
  36. $("#results").empty();
  37. var jsonObject = JSON.parse(data.body);
  38. var odataResults = jsonObject.d.results;
  39. // set rendering template
  40. var tableHeader = "<thead>" +
  41. "<td>Last Name</td>" +
  42. "<td>First Name</td>" +
  43. "<td>Work Phone</td>" +
  44. "<td> </td>" +
  45. "<td> </td>" +
  46. "<td> </td>" +
  47. "</thead>";
  48. var table = $("<table>", { id: "customersTable" }).append($(tableHeader));
  49. var renderingTemplate = "<tr>" +
  50. "<td>{{>Title}}</td>" +
  51. "<td>{{>FirstName}}</td>" +
  52. "<td>{{>WorkPhone}}</td>" +
  53. "<td><a href='javascript: onShowCustomerDetail({{>Id}});'><img src='_layouts/images/DETAIL.gif' alt='Show Detail' /></a></td>" +
  54. "<td><a href='javascript: onUpdateCustomer({{>Id}});'><img src='_layouts/images/EDITITEM.gif' alt='Edit' /></a></td>" +
  55. "<td><a href='javascript: onDeleteCustomer({{>Id}});'><img src='_layouts/images/DELITEM.gif' alt='Delete' /></a></td>" +
  56. "</tr>";
  57. $.templates({ "tmplTable": renderingTemplate });
  58. table.append($.render.tmplTable(odataResults));
  59. $("#results").append(table);
  60. }

Step 5: Add new customer

EditCustomer.aspx file contains code for New Customer Popup.

  1. <%@ Page Language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  2. <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  3. <%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  4. <%@ Register TagPrefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
  5. <asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
  6. <link rel="Stylesheet" type="text/css" href="../Content/App.css" />
  7. <SharePoint:ScriptLink name="SP.UI.Dialog.js" runat="server" Defer="false" LoadAfterUI="true" Localizable="false" />
  8. <SharePoint:ScriptLink name="sp.js" runat="server" Defer="false" LoadAfterUI="true" Localizable="false" />
  9. <script type="text/javascript" src="../Scripts/jquery-1.6.2.js"></script>
  10. <script type="text/javascript" src="../Scripts/EditCustomer.js"></script>
  11. </asp:Content>
  12. <asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
  13. <div class="dialog_input_section">
  14. <table id="customerEditTable">
  15. <tr>
  16. <td>First Name:</td>
  17. <td>
  18. <input id="txtFirstName" /></td>
  19. </tr>
  20. <tr>
  21. <td>Last Name:</td>
  22. <td>
  23. <input id="txtLastName" /></td>
  24. </tr>
  25. <tr>
  26. <td>Work Phone:</td>
  27. <td>
  28. <input id="txtWorkPhone" /></td>
  29. </tr>
  30. </table>
  31. </div>
  32. <div class="dialog_button_section">
  33. <input type="button" id="cmdOK" value="Save" class="ms-ButtonHeightWidth" />
  34. <input type="button" id="cmdCancel" value="Cancel" class="ms-ButtonHeightWidth" />
  35. </div>
  36. </asp:Content>

App.JS file contains the following code to open popup.

  1. $("#cmdAddNewCustomer").click(onAddCustomer);
Above click internally calls EditCustomer.aspx file and render it on screen.


Step 6: Update Customer

Inside GridView, edit button is provided to update existing customer details.

Code:
  1. function onUpdateCustomer(customer) {
  2. var executor = new SP.RequestExecutor(appweburl);
  3. var FullURL = appweburl + "/_api/web/lists/getbytitle('Customers')/items(" + customer + ")";
  4. executor.executeAsync(
  5. {
  6. url: FullURL,
  7. method: "GET",
  8. headers: {
  9. "accept": "application/json;odata=verbose",
  10. "content-type": "application/json;odata=verbose",
  11. "X-RequestDigest": $("#__REQUESTDIGEST").val()
  12. },
  13. success: onCustomerReturned,
  14. error: errorHandler
  15. }
  16. );
  17. }
Output


Step 7: Delete Customer

Inside GridView, delete button is provided to delete existing customer details.

Code
  1. function onDeleteCustomer(customer) {
  2. var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/getByTitle('Customers')/items(" + customer + ")";
  3. var requestHeaders = {
  4. "accept": "application/json",
  5. "X-RequestDigest": $("#__REQUESTDIGEST").val(),
  6. "If-Match": "*"
  7. }
  8. $.ajax({
  9. url: requestUri,
  10. type: "DELETE",
  11. contentType: "application/json",
  12. headers: requestHeaders,
  13. success: onSuccess,
  14. error: onError
  15. });
  16. }

Step 8: View Customer Details.

Inside GridView, view button is provided to view existing customer details.

  1. function onShowCustomerDetail(customer) {
  2. var customerItemEditUrl = _spPageContextInfo.webAbsoluteUrl +
  3. "/Lists/Customers/DispForm.aspx?ID=" + customer;
  4. var dialogOptions = {
  5. url: customerItemEditUrl,
  6. title: "Customer Detail",
  7. dialogReturnValueCallback: getCustomers
  8. };
  9. SP.UI.ModalDialog.showModalDialog(dialogOptions);
  10. }
Output

When view form is open in browser and if you change user details there itself it gets updated and final result get rendered on screen.

Full Source Code
  1. var hostweburl;
  2. var appweburl;
  3. $(function () {
  4. // register event handlers on page
  5. $("#cmdAddNewCustomer").click(onAddCustomer);
  6. $("#results").append($("<img>", { src: "_layouts/images/gears_anv4.gif" }));
  7. // Get the URI decoded URLs.
  8. hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
  9. appweburl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl"));
  10. var scriptbase = hostweburl + "/_layouts/15/";
  11. $.getScript(scriptbase + "SP.RequestExecutor.js", getCustomers);
  12. });
  13. function getCustomers() {
  14. $("#results").empty();
  15. $("<img>", { "src": "/_layouts/images/GEARS_AN.GIF" }).appendTo("#results");
  16. var executor = new SP.RequestExecutor(appweburl);
  17. var FullURL = appweburl + "/_api/web/lists/getbytitle('Customers')/items";
  18. executor.executeAsync(
  19. {
  20. url: FullURL,
  21. method: "GET",
  22. headers: {
  23. "accept": "application/json;odata=verbose",
  24. "content-type": "application/json;odata=verbose",
  25. "X-RequestDigest": $("#__REQUESTDIGEST").val()
  26. },
  27. success: onDataReturned,
  28. error: errorHandler
  29. }
  30. );
  31. }
  32. function errorHandler(data, errorCode, errorMessage) {
  33. document.getElementById("results").innerText = "Could not complete cross-domain call: " + errorMessage;
  34. }
  35. function onDataReturned(data) {
  36. $("#results").empty();
  37. var jsonObject = JSON.parse(data.body);
  38. var odataResults = jsonObject.d.results;
  39. // set rendering template
  40. var tableHeader = "<thead>" +
  41. "<td>Last Name</td>" +
  42. "<td>First Name</td>" +
  43. "<td>Work Phone</td>" +
  44. "<td> </td>" +
  45. "<td> </td>" +
  46. "<td> </td>" +
  47. "</thead>";
  48. var table = $("<table>", { id: "customersTable" }).append($(tableHeader));
  49. var renderingTemplate = "<tr>" +
  50. "<td>{{>Title}}</td>" +
  51. "<td>{{>FirstName}}</td>" +
  52. "<td>{{>WorkPhone}}</td>" +
  53. "<td><a href='javascript: onShowCustomerDetail({{>Id}});'><img src='_layouts/images/DETAIL.gif' alt='Show Detail' /></a></td>" +
  54. "<td><a href='javascript: onUpdateCustomer({{>Id}});'><img src='_layouts/images/EDITITEM.gif' alt='Edit' /></a></td>" +
  55. "<td><a href='javascript: onDeleteCustomer({{>Id}});'><img src='_layouts/images/DELITEM.gif' alt='Delete' /></a></td>" +
  56. "</tr>";
  57. $.templates({ "tmplTable": renderingTemplate });
  58. table.append($.render.tmplTable(odataResults));
  59. $("#results").append(table);
  60. }
  61. function onShowCustomerDetail(customer) {
  62. var customerItemEditUrl = _spPageContextInfo.webAbsoluteUrl +
  63. "/Lists/Customers/DispForm.aspx?ID=" + customer;
  64. var dialogOptions = {
  65. url: customerItemEditUrl,
  66. title: "Customer Detail",
  67. dialogReturnValueCallback: getCustomers
  68. };
  69. SP.UI.ModalDialog.showModalDialog(dialogOptions);
  70. }
  71. function onAddCustomer(event) {
  72. var dialogArgs = {
  73. command: "Add"
  74. };
  75. var dialogOptions = {
  76. url: "EditCustomer.aspx",
  77. title: "Add New Customer",
  78. width: "480px",
  79. args: dialogArgs,
  80. dialogReturnValueCallback: saveNewCustomer
  81. };
  82. SP.UI.ModalDialog.showModalDialog(dialogOptions);
  83. }
  84. function saveNewCustomer(dialogResult, returnValue) {
  85. if (dialogResult == SP.UI.DialogResult.OK) {
  86. // get data from dialog for new customer
  87. var LastName = returnValue.LastName;
  88. var FirstName = returnValue.FirstName;
  89. var WorkPhone = returnValue.WorkPhone;
  90. var requestUri = _spPageContextInfo.webAbsoluteUrl +
  91. "/_api/Web/Lists/getByTitle('Customers')/items/";
  92. var requestHeaders = {
  93. "accept": "application/json",
  94. "X-RequestDigest": $("#__REQUESTDIGEST").val(),
  95. }
  96. var customerData = {
  97. Title: LastName,
  98. FirstName: FirstName,
  99. WorkPhone: WorkPhone
  100. };
  101. requestBody = JSON.stringify(customerData);
  102. $.ajax({
  103. url: requestUri,
  104. type: "Post",
  105. contentType: "application/json",
  106. headers: requestHeaders,
  107. data: requestBody,
  108. success: onSuccess,
  109. error: onError
  110. });
  111. }
  112. }
  113. function onDeleteCustomer(customer) {
  114. var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/getByTitle('Customers')/items(" + customer + ")";
  115. var requestHeaders = {
  116. "accept": "application/json",
  117. "X-RequestDigest": $("#__REQUESTDIGEST").val(),
  118. "If-Match": "*"
  119. }
  120. $.ajax({
  121. url: requestUri,
  122. type: "DELETE",
  123. contentType: "application/json",
  124. headers: requestHeaders,
  125. success: onSuccess,
  126. error: onError
  127. });
  128. }
  129. function onUpdateCustomer(customer) {
  130. var executor = new SP.RequestExecutor(appweburl);
  131. var FullURL = appweburl + "/_api/web/lists/getbytitle('Customers')/items(" + customer + ")";
  132. executor.executeAsync(
  133. {
  134. url: FullURL,
  135. method: "GET",
  136. headers: {
  137. "accept": "application/json;odata=verbose",
  138. "content-type": "application/json;odata=verbose",
  139. "X-RequestDigest": $("#__REQUESTDIGEST").val()
  140. },
  141. success: onCustomerReturned,
  142. error: errorHandler
  143. }
  144. );
  145. }
  146. function onCustomerReturned(data) {
  147. var jsonObject = JSON.parse(data.body);
  148. var dialogArgs = {
  149. command: "Update",
  150. Id: jsonObject.d.Id,
  151. LastName: jsonObject.d.Title,
  152. FirstName: jsonObject.d.FirstName,
  153. WorkPhone: jsonObject.d.WorkPhone,
  154. etag: jsonObject.d.__metadata.etag
  155. };
  156. var dialogOptions = {
  157. url: "EditCustomer.aspx",
  158. title: "Update Customer",
  159. width: "480px",
  160. args: dialogArgs,
  161. dialogReturnValueCallback: updateCustomer
  162. };
  163. SP.UI.ModalDialog.showModalDialog(dialogOptions);
  164. }
  165. function updateCustomer(dialogResult, returnValue) {
  166. if (dialogResult == SP.UI.DialogResult.OK) {
  167. var Id = returnValue.Id;
  168. var FirstName = returnValue.FirstName;
  169. var LastName = returnValue.LastName;
  170. var WorkPhone = returnValue.WorkPhone;
  171. var etag = returnValue.etag;
  172. var requestUri = appweburl + "/_api/web/lists/getbytitle('Customers')/items(" + Id + ")";
  173. var requestHeaders = {
  174. "accept": "application/json",
  175. "X-RequestDigest": $("#__REQUESTDIGEST").val(),
  176. "X-HTTP-Method": "MERGE",
  177. "If-Match": etag
  178. }
  179. var customerData = {
  180. Title: LastName,
  181. FirstName: FirstName,
  182. WorkPhone: WorkPhone
  183. };
  184. requestBody = JSON.stringify(customerData);
  185. $.ajax({
  186. url: requestUri,
  187. type: "POST",
  188. contentType: "application/json",
  189. headers: requestHeaders,
  190. data: requestBody,
  191. success: onSuccess,
  192. error: onError
  193. });
  194. }
  195. }
  196. function onSuccess(data, request) {
  197. getCustomers();
  198. }
  199. function onError(error) {
  200. $("#results").empty();
  201. $("#results").text("ADD ERROR: " + JSON.stringify(error));
  202. }
  203. function getQueryStringParameter(paramToRetrieve) {
  204. var strParams = "";
  205. var params = document.URL.split("?")[1].split("&");
  206. for (var i = 0; i < params.length; i = i + 1) {
  207. var singleParam = params[i].split("=");
  208. if (singleParam[0] == paramToRetrieve)
  209. return singleParam[1];
  210. }
  211. }
App.css
  1. .ms-siteicon-a {
  2. background-image: url(images/SiteIcon.gif);
  3. background-repeat: no-repeat;
  4. width: 75px;
  5. height: 75px;
  6. }
  7. .ms-siteicon-img {
  8. display: none;
  9. }
  10. .ms-core-siteTitle span a {
  11. font-size: 18px;
  12. }
  13. #customersTable {
  14. background-color: #999;
  15. border-collapse: collapse;
  16. }
  17. #customersTable thead td {
  18. background-color: #333;
  19. color: White;
  20. }
  21. #customersTable td {
  22. color: #222;
  23. border: 1px black solid;
  24. padding: 4px;
  25. background-color: White;
  26. border-collapse: collapse;
  27. }
  28. #resultsTable tr td {
  29. color: #333;
  30. padding: 4px;
  31. border-collapse: collapse;
  32. border: 1px solid black;
  33. background-color: White;
  34. font-size: 32px;
  35. }
  36. #toolbar {
  37. margin: 4px;
  38. padding: 8px;
  39. background-color: #ccc;
  40. }
  41. #results {
  42. padding: 8px;
  43. font-size: 12px;
  44. }
  45. #results table {
  46. margin: 8px
  47. }
  48. #results table, #results table td {
  49. border-collapse: collapse;
  50. border: 1px #444 solid;
  51. padding: 2px 8px 2px 4px;
  52. font-size: 20px;
  53. }
  54. #results h2 {
  55. font-size: 18px;
  56. color: #999;
  57. border-bottom: 1px solid #999;
  58. margin-top: 8px;
  59. margin-bottom: 4px;
  60. }
  61. .ms-dialog #s4-ribbonrow {
  62. display: none;
  63. }
  64. .ms-dlgTitle {
  65. background-image: url("images/logo16.gif");
  66. background-repeat: no-repeat;
  67. background-position: 8px, 4px;
  68. background-color: black;
  69. padding: 1px;
  70. }
  71. h1.ms-dlgTitleText {
  72. margin-left: 28px;
  73. margin-top: 4px;
  74. }
  75. .ms-dlgTitle h1 {
  76. font-size: 1.4em;
  77. color: white;
  78. }
  79. #dlgTitleBtns {
  80. margin-top: 4px;
  81. margin-right: 8px;
  82. }
  83. .ms-dlgTitle {
  84. padding-bottom: 4px;
  85. padding-left: 8px;
  86. }
  87. .ms-dlgTitle h1 {
  88. font-size: 1.8em;
  89. }
  90. .dialog_input_section {
  91. padding-top: 4px;
  92. }
  93. .dialog_input_section_title {
  94. margin-top: 8px;
  95. color: black;
  96. border-bottom: solid black 1px;
  97. margin-bottom: 8px;
  98. }
  99. .dialog_button_section {
  100. margin-top: 16px;
  101. border-top: solid #CCC 2px;
  102. padding-top: 8px;
  103. text-align: right;
  104. }
  105. .ms-dlgContent {
  106. padding-bottom: 2px;
  107. }
  108. .ms-dlgFrameContainer {
  109. padding-top: 4px;
  110. padding-left: 8px;
  111. padding-right: 8px;
  112. padding-bottom: 0px;
  113. }