Skip to content

Instantly share code, notes, and snippets.

Last active Dec 28, 2015
What would you like to do?
Demo of Knockout.js with SharePoint 2013 - Removing Items
/* Place custom styles below */
.tableStyle {
border: 1px solid black;
.messages {
#success {
#failure {
'use strict';
//global variables
var hostWebUrl;
var appWebUrl;
var listItems;
var list;
var context;
var completeCountryList;
//this array is to keep tab of those countries that are added or removed
var changedCountries = [];
$(document).ready(function () {
//get the url of app web and host web
hostWebUrl = QS("SPHostUrl");
appWebUrl = QS("SPAppWebUrl");
//class for saving the countries and their states
function CountryList(countryName, stateName, id, isUpdated) {
var self = this;
self.CountryName = countryName;
self.StateName = stateName;
//Sharepoint List Item ID
self.Id = id;
//IsUpdated is just to keep tab of rows that are added/removed from the table. This is not a SP column
self.IsUpdated = isUpdated;
//View Model to combine data from list into the format which view expects
function CountryListViewModel() {
var self = this;
self.Countries = ko.observableArray([]);
self.AddCountries = function (countryName, stateName, id, isUpdated) {
self.Countries.push(new CountryList(countryName, stateName, id, isUpdated));
//hide success message
self.RemoveCountries = function (country) {
//to keep tab of countries that are removed
//hide success message
//Update SP list with the changes in view model
self.UpdateSPList = function () {
/* this variable checks if empty string is passed in either of the state or country name
in this case the value is not updated in SP */
var emptyValues = false;
//create array of only those rows that are updated
$.each(self.Countries(), function () {
if (this.IsUpdated == true) {
//if either of the country or state name is blank skip the entry
if (this.CountryName.length > 0 && this.StateName.length > 0) {
this.IsUpdated = false;
else {
emptyValues = true;
//show error message if even one of the entry is blank
if (emptyValues) {
$("#failure").text("Empty values are not updated in sharepoint");
else {
//if there are no updates
if (changedCountries.length == 0) {
alert("No Items to update");
else {
//function to update corresponding sharepoint list
function SubmitDataToSP(changedCountries) {
$.each(changedCountries, function () {
//for newly added entries id will be 0
if (this.Id == 0) {
var itemCreateInfo = new SP.ListItemCreationInformation();
var newListItem = list.addItem(itemCreateInfo);
newListItem.set_item("CountryName", this.CountryName);
newListItem.set_item("StateName", this.StateName);
else {
//if id is not 0 that means this item should be deleted
var deletedItem = list.getItemById(this.Id);
context.executeQueryAsync(ItemAdded, Failed);
//empty the changed countries array for further processing
changedCountries.length = 0;
function ItemAdded() {
//give a success message
$("#success").text("Item are successfull updated");
//function which apply KO bindings and make a call to SP using CSOM
function LoadData() {
completeCountryList = new CountryListViewModel();
//get items from SP list
function GetList() {
context = new SP.ClientContext(appWebUrl);
//No need to use SP.RequestExecutor.js for cross domain calls to host web in SP Hosted web
/* var factory = new SP.ProxyWebRequestExecutorFactory(appWebUrl);
context.set_webRequestExecutorFactory(factory); */
var hostContext = new SP.AppContextSite(context, hostWebUrl);
list = hostContext.get_web().get_lists().getByTitle("KnockoutList");
var camlQuery = new SP.CamlQuery();
listItems = list.getItems(camlQuery);
context.load(listItems, "Include(Id, CountryName, StateName)");
context.executeQueryAsync(ListItemsLoaded, Failed);
function ListItemsLoaded(sender, args) {
var enumerator = listItems.getEnumerator();
while (enumerator.moveNext()) {
var currentItem = enumerator.get_current();
completeCountryList.AddCountries(currentItem.get_item("CountryName"), currentItem.get_item("StateName"), currentItem.get_id(), false);
function Failed(sender, args) {
function QS(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(;
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
<div id="divCountryList">
<h2>Country List</h2>
<br />
<table id="tblCountryList" border="1" class="tableStyle">
<!-- Iterating through every list item using foreach of KO -->
<tbody data-bind="foreach: Countries">
<td><input data-bind="value: CountryName" /></td>
<td><input data-bind="value: StateName" /></td>
<td><a href="#" data-bind="click: $root.RemoveCountries">Remove this</a></td>
<br />
<button data-bind="click: AddCountries.bind($data, '', '', 0, true)">Add State</button>
<button data-bind="click: UpdateSPList">Submit to SharePoint</button>
<br />
<div id="success" class="messages"></div>
<br />
<div id="failure" class="messages"></div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment