Skip to content

Instantly share code, notes, and snippets.

@danawesome
Last active October 20, 2022 16:08
Show Gist options
  • Select an option

  • Save danawesome/097edd39ede74ad0608de8289b4ec82c to your computer and use it in GitHub Desktop.

Select an option

Save danawesome/097edd39ede74ad0608de8289b4ec82c to your computer and use it in GitHub Desktop.
SharePoint REST API Delete List Items

Answer to StackExchange SharePoint Question "Deleteing SharePoint List elements with specific values in a column"

Sample Example: using REST API and ES6

I wanted to provide an example that doesn't use jQuery.

The answer is longer than it strictly needs to be. However, if you are doing this a lot, the helpers and utility functions, with some light error handling, come in handy.

The code below assumes you have JSON Light enabled in your SharePoint Environment. (Supported in 2013 via SP1 and add some assembly references to the web.config. JSON Light is present in 2016, 2019, SPO. Not supported in 2010)

const myListName = "Your-List-Name-Here";
const getObj = {
	method: "GET",
	// INFO passes along the windows credentials, adjust to suit your environment
	credentials: "include",
	headers: {
		Accept: "application/json;odata=nometadata",
		"Content-Type": "application/json;odata=nometadata",
	},
};
const delObj = {
	method: "POST",
	// INFO passes along the windows credentials, adjust to suit your environment
	credentials: "include",
	headers: {
		Accept: "application/json;odata=nometadata",
		"Content-Type": "application/json;odata=nometadata",
		"X-RequestDigest": "",
		"IF-MATCH": "*",
		"X-HTTP-Method": "DELETE"
	},
};
const listUrl = 
`${_spPageContextInfo.webAbsoluteUrl}/_api/web/lists/getbytitle('${myListName}')`;

// INFO Main Function to call.
function deleteListItems () {
	/* INFO You will need to modify this so it filters correctly on your columns
	Returns just the Id values, and limits results to the top newest 5000 items.
	5000 items is the max and is part of the built-in throttle limit. 
    You can get the next 5000 items without too much hassle.*/
	const url = 
    `${listUrl}/Items?$select=Id&$orderby=Id desc&$top=5000&$filter=(Age eq 30) and (Country eq 'US')`;
	const result = fetchWrapper(url, getObj);
	// INFO all the items' ID's that match the filter
	// INFO 'async' is only needed it freshness function used.
    result.then(async (items) => {
		/* INFO Use a freshness function to avoid errors on pages that
           a user might sit at longer than 20 minutes*/
		const digest = await testIfDigestFresh();
		// INFO or just get it from the page
		// const digest = document.getElementById("__REQUESTDIGEST").value;
		// INFO create an array of urls for each item Id to delete
		const urlArr = items.value.map(item => {
			return `${listUrl}/Items(${item.Id})`;
		});
		// INFO inject the SharePoint Request Digest value, will fail otherwise.
		delObj.headers["X-RequestDigest"] = digest;
		/* INFO Process all the items to delete as an asynchronous 
           promise wrapped group */
		const itemsDeleted = Promise.all(urlArr.map(url=>fetchWrapper(url, delObj)));
		// INFO Do any post processing or messages.
		itemsDeleted.then(data => {
			/* INFO SharePoint only responds with just 200, no body.
					Counting how many array items are return from the
					promise will provide a total count.
			*/
			console.log("Deleted:", data.length);
			alert(`'${data.length}' Items Deleted`);
		})
		.catch(err => {
			alert('Request failed.', err);
		});
	});
}

// UTIL Functions
	/* INFO Abstracts fetch, handle non-json responses, add custom error messages, 
       default settings */
	async function fetchWrapper(url, options, custom_err_msg) {
		if (!url) {
			throw new Error("url is missing");
		}
		let opt;
		if (options) {
			opt = options;
		} else {
			opt = {
				method: "GET",
				mode: "no-cors",
				headers: {
					"Content-Type": "application/json",
					Accept: "application/json",
				},
			};
		}
		return fetch(url, opt)
			.then(async (resp) => {
				if (!resp.ok) {
					throw new Error(resp.status);
				}
				// HANDLE not json
				try {
					let json = await resp.json();
					return json;
				} catch (error) {
					console.log("catch error, not json, try text", error);
					return resp.text();
				}
			})
			.then((data) => {
				return data;
			})
			.catch((err) => {
				// HANDLE errors and custom error messages, must be a string
				if (custom_err_msg && typeof custom_err_msg === "string") {
					console.error(`${custom_err_msg}`, err);
					return `${custom_err_msg}\n${err.statusText}`;
				} else {
					if (err.toString().substr(7, err.length) == 404) {
						return "Not found";
					} else {
						return err;
					}
				}
			});
	}
// OPTIONAL Helper Functions
	function msToMinAndSecs(ms) {
		const minutes = Math.floor(ms / 60000);
		// INFO turn on if seconds are needed
		// const seconds = ((ms % 60000) / 1000).toFixed(0);
		return minutes; // + ":" + (ms < 10 ? '0' : '') + seconds;
	}

	async function testIfDigestFresh() {
		let isFresh;
		const lastLoaded = new Date(window.parent.g_updateFormDigestPageLoaded);
		const now = new Date();
		const compared = now - lastLoaded;
		const diff = msToMinAndSecs(compared);
		if (diff >= 24) {
			isFresh = await getDigest();
		} else {
			isFresh = window.parent.document.getElementById("__REQUESTDIGEST").value;
			console.log("digest still fresh");
		}
		return isFresh;
	}

	async function getDigest() {
		const url = `${_spPageContextInfo.webAbsoluteUrl}/_api/contextinfo`;
		/* INFO Didn't use fetchWrapper so function wouldn't depend on the wrapper
           to work. */
		return fetch(url, {
			method: "POST",
			credentials: "include",
			headers: {
				"Content-Type": "application/json; odata=nometadata",
				Accept: "application/json; odata=nometadata",
			},
		})
		.then((r) => r.json())
		.then((json) => {
			let digest = json.FormDigestValue;
			const digestTime = new Date(digest.split(",")[1]);
			// INFO Update the digest on the SharePoint Page
			window.parent.document.getElementById("__REQUESTDIGEST").value = digest;
			// INFO Update the time since last digest received to fresh date.
			window.parent.g_updateFormDigestPageLoaded = digestTime;
			return true;
		})
		.catch((err) => {
			console.error("Error from GetDigest():\n", err);
			return false;
		});
	}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment