I have been working on a project for quite some time now.
I have found this post somewhat useful, but am unsure if it is correct or not for my utilization.
Functionality:
Read in SharePoint list items from 8 different subsites with a GET request.
Populate those items in an orderly(grouped) fashion in a DataTable on a single landing page.
DataTable has collapsible/expandable rows grouped by program, followed by deliverable.
Dropdown menu with buttons to print/excel/PDF/Update the table.
Update Table has a HTML form that sends data back to the SharePoint List correlated with the FORM input.
I am currently using 8 different subsites where all of the lists are located. I want to send the new item to the correct list based off of its "Program" value because each of the different lists are a different program. I know I would have to use an if/else statement, but how would I go about that with an AJAX call?
Here is my JS "POST" Code:
$("#btn").click(function(e) {
PostItem();
});
});
function PostItem() {
return getFormDigest("https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/Lists/AMMODeliverables/").then(function(digestData) {
console.log(digestData.d.GetContextWebInformation.FormDigestValue);
var item = {
"__metadata": { "type": "SP.Data.AMMODeliverablesListItem" },
"Title": "updated title",
"Program": $("#dProgram").val(),
"Deliverable": $("#dDeliverable").val(),
"To": $("#dTo").val(),
"Date": $("#dDate").val(),
"Approved": $("#dApproved").val(),
"Notes": $("#dNotes").val()
};
$.ajax({
async: true, // Async by default is set to “true” load the script asynchronously
// URL to post data into sharepoint list or your own url
url: "https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/web/lists/getbytitle('AMMO Deliverables')/items",
method: "POST", //Specifies the operation to create the list item
data: JSON.stringify(item),
headers: {
"content-type": "application/json;odata=verbose",
"X-RequestDigest": digestData.d.GetContextWebInformation.FormDigestValue,
"Accept": "application/json;odata=verbose",
"If-Match": "*"
},
success: function(data) {
alert('Success'); // Used sweet alert for success message
console.log(data + " success in updating item");
},
error: function(data) {
alert(JSON.stringify(item));
console.log(data);
}
});
})
}
function getItemTypeForListName(listName) {
var itemType = "SP.Data." + listName.charAt(0).toUpperCase() + listName.slice(1) + "ListName";
var encItemType = itemType.replace(/\s/g,'_x0020_');
return(encItemType);
}
function getFormDigest(baseurl) {
return $.ajax({
url: "https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/contextInfo",
method: 'POST',
headers: {
'Accept': 'application/json; odata=verbose'
}
});
}
UPDATE:
I feel like I am somewhat in the right direction, but it doesn't work:
function PostItem() {
return getFormDigest("https://siteurl.sharepoint.com/sites/Projects/USMC/AMMO/Lists/AMMODeliverables/").then(function(digestData) {
console.log(digestData.d.GetContextWebInformation.FormDigestValue);
var item = {
"__metadata": { "type": "SP.Data.AMMODeliverablesListItem" },
"Title": "updated title",
"Program": $("#dProgram").val(),
"Deliverable": $("#dDeliverable").val(),
"To": $("#dTo").val(),
"Date": $("#dDate").val(),
"Approved": $("#dApproved").val(),
"Notes": $("#dNotes").val()
};
if (dProgram == "AMMO"){
$.ajax({
async: true, // Async by default is set to “true” load the script asynchronously
// URL to post data into sharepoint list or your own url
url: "https://siteurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/web/lists/getbytitle('AMMO Deliverables')/items",
method: "POST", //Specifies the operation to create the list item
data: JSON.stringify(item),
headers: {
"content-type": "application/json;odata=verbose",
"X-RequestDigest": digestData.d.GetContextWebInformation.FormDigestValue,
"Accept": "application/json;odata=verbose",
"If-Match": "*"
},
success: function(data) {
alert('Success'); // Used sweet alert for success message
console.log(data + " success in updating item");
},
error: function(data) {
alert(JSON.stringify(item));
console.log(data);
}
});
}
else if (dProgram == "AHR"){
First of all, your getFormDigest function is not quite right:
function getFormDigest(baseurl) {
// you pass in a "baseurl" value above, but you're not really doing anything with it.
// the URL you use below is hardcoded to always
// make the request to the /sites/Projects/USMC/AMMO site
return $.ajax({
url: "https://baseurl.sharepoint.com/sites/Projects/USMC/AMMO/_api/contextInfo",
method: 'POST',
headers: {
'Accept': 'application/json; odata=verbose'
}
});
}
What you need to do is change that so you can pass a site URL into it and get a valid form digest from the actual site you are trying to post a new item to:
function getFormDigest(siteUrl) {
return $.ajax({
url: siteUrl + "/_api/contextInfo",
method: 'POST',
headers: {
'Accept': 'application/json; odata=verbose'
}
});
}
Next, you need to change your PostItem function to react to the current value of the selected Program, and choose some correct values based on that. I see in the comments you have posted a little snippet where you are creating a map that will spit out the correct URL based on the key of the selected Program. That works if all you need is a single value, however, since you said that the list names are all different on each subsite, you actually need three different values to be generated dynamically based on the selected Program:
The URL to the site itself so you can get a valid form digest,
The list name, so you can get the correct List Item Entity Type value for your new item's JSON __metadata property. You have a function to do this, but you aren't using it. Also, you'll need the list name for:
A URL that includes the site and the list name so you can post the new list item (since the URL to do that is essentially [URL to site]/_api/web/lists/getbytitle('[list name]')/items)
You could do a sequence of if..then..else if..then..else if..then..else statements, but for more than two or three possible values, that gets cumbersome. A much cleaner way of doing it is using a switch statement. So here's what your PostItem function might look like if you used a switch to evaluate what the selected Program value is and then dynamically set the site URL and list name based on that:
function PostItem() {
// the base URL should be what is the same across all subsites. in comments
// you said the subsites start to differ after /sites/Projects.
var baseUrl = "https://your-tenant.sharepoint.com/sites/Projects";
// get the selected program from your form
var programName = $("#dProgram").val();
var siteUrl = null; // set this as empty for now
var listName = null; // set this as empty for now
// a "switch" statement is like a fancy "if" statement that is
// useful if you have more than just two or three options
switch (programName) {
case "AMMO":
// set the site url to be whatever it is after /sites/Projects.
// in the case of AMMO, you have already posted that the "AMMO"
// subsite is under a "USMC" subsite that is under "Projects"
siteUrl = baseUrl + "/USMC/AMMO";
listName = "AMMODeliverables";
break;
case "AHR":
// set the site url to be whatever it is after /sites/Projects.
// IF in this case the "AHR" subsite is directly under /Projects
// and NOT under another subsite (as is the case with /USMC/AMMO),
// you just add that directly:
siteUrl = baseUrl + "/AHR";
// HOWEVER, if it is under another subsite with a different name, similar
// to how "AMMO" is actually under another subsite called "USMC", then you
// would include that "Other" subsite here:
siteUrl = baseurl + "/Other/AHR";
// set the list name, since you said the list names
// are different in each of the subsites
listName = "AHR Deliverables";
break;
case "FOO":
// pretending that "FOO" is _directly_ under /sites/Projects
siteUrl = baseurl + "/FOO";
listName = "FOO Thingys";
break;
case "BAR":
// pretending that "BAR" is NOT directly under /sites/Projects,
// but is in fact under another "Different" subsite
siteUrl = baseurl + "/Different/BAR";
listName = "BAR Whatchamacallits";
default:
// all switch statements need a default option in case
// what we are checking does not match any any of the options
// we are expecting. in this instance, we will _not_ set
// a site URL or list name so that we do not try to post
// to s non-existent site or list
break;
}
// if we didn't get one of our expected choices for programName, then siteUrl
// will not have been populated in the switch, so we can check and make sure we
// actually have a valid siteUrl before we start sending AJAX requests out
if (siteUrl) {
// pass the siteUrl into your improved getFormDigest function so
// that you get the correct form digest from the site you are
// actually trying to post a new item to.
// also, you don't actuall need the "return" here.
getFormDigest(siteUrl).then(function(digestData) {
console.log(digestData.d.GetContextWebInformation.FormDigestValue);
// use your getItemTypeForListName function to get the
// correct SharePoint List Item Entity Type name based on
// the list name
var listItemEntityType = getItemTypeForListName(listName);
// construct the URL to post the new list item to based on the siteUrl
// and the listName, which vary based on the selected projecName
var postNewItemUrl = siteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items";
// construct your new item JSON. you said all the fields
// in all the lists are the same, so the only thing that really
// needs to dynamically chage here is the entity type name,
// which was generated based on the list name
var item = {
"__metadata": { "type": listItemEntityType },
"Title": "updated title",
"Program": programName,
"Deliverable": $("#dDeliverable").val(),
"To": $("#dTo").val(),
"Date": $("#dDate").val(),
"Approved": $("#dApproved").val(),
"Notes": $("#dNotes").val()
};
$.ajax({
// use your dynamically generated URL here
url: postNewItemUrl,
method: "POST", //Specifies the operation to create the list item
data: JSON.stringify(item),
headers: {
"content-type": "application/json;odata=verbose",
"X-RequestDigest": digestData.d.GetContextWebInformation.FormDigestValue,
"Accept": "application/json;odata=verbose",
"If-Match": "*"
},
success: function(data) {
alert('Success'); // Used sweet alert for success message
console.log(data + " success in updating item");
},
error: function(data) {
alert(JSON.stringify(item));
console.log(data);
}
});
});
}
}
Related
I am having a hard time figuring how to filter and update the API on the filtered orders:
In the Shopify orders panel, I did an API call and got a list of all orders. I achieve to only update 1 array with the put method but it's not dynamic. So basically what i am trying to do is :
Btw this is all javascript
GET api call for all orders then filter the orders who have BOTH country Canada and blank phone number then on those orders with canada and blank number, i tried to update them with PUT method to change the number to "dummy number" but can't apply that on only those orders with canada and blank number. I did get all the orders and i got array of objects of 6 order. This is my code so far.
$(document).ready(function () {
// this is valid url and returns all orders
var api_url = "https://($api-domain-bla-bla)/admin/api/2020-10/orders.json?status=any.json";
$.ajax({
url: api_url,
contentType: "application/json",
dataType: "json",
success: function (result) {
console.log(result);
// get all orders phone country
let orders = result.orders;
console.log(orders);
for(let i = 0; i < orders.length;i++) {
let phone = orders[i].shipping_address.phone;
let country = orders[i].shipping_address.country;
// here i am trying to filter them right away but don't know how to make array of filter objects
// the if statement works
if ( country === "Canada" && phone === '') {
// over here i am trying to do something to those objects which if statement is true.
let filteredOrder = orders[i].concat
console.log(orderId);
// a function with parameter of the filtere objects variable, to the api PUT method to update
// the filter orders/objects
checkCountry(filteredOrder);
}
// console.log(phone);
// console.log(country);
// checkPhone(phone, country);
}
},
});
});
this is what I get from console.log(result)
https://prnt.sc/vls9qq
https://prnt.sc/vlsh55 (api from all orders)
function checkCountry(order) {
// here i want to update the orders with canada and blank phone number, to put "00000" on the phone
//number i had code here with some if statements but i figured it wouldn't work so i am trying new way
//to get it to work
var api_url_post = "https://($api-domain-bla-bla)/admin/api/2020-10/orders.json?status=any.json";
// this phone variable the structure is the same with the one i get from the call above, don't know
// why it doesn't accept it.
var phone = {
"orders":
{
// "id": 1843613401136,
// "phone": "+0000000000",
"shipping_address": {
"phone": "0000000000"
}
},
}
$.ajax({
method: "PUT",
url: api_url_post,
contentType: "application/json",
crossDomain: true,
dataType: "json",
data: JSON.stringify(phone),
success: function (data, status, jqXHR) {
alert("success");// write success in " "
},
error: function (jqXHR, status) {
// error handler
console.log(jqXHR);
alert('fail' + status.code);
}
});
}
Sorry if I made it unclear, any help?
I am not sure what you are trying to accomplish. My understanding is this:
You are making an API request to get a list of orders.
You want to filter that list for the orders from canada without a phone number.
You want to edit the filtered list with dummy phone numbers and put these changes to server.
I dont know much about how the api for getting/putting orders is written, so I what I have in mind may not be efficient. I would map over all the orders and change the Canadian orders without a phone number
orders = orders.map(order=>{
let {country, phone } = order.shipping_address
if(country === "Canada" && phone === ''){
order.shipping_address.phone = '0000000'
}
return order
})
And instead of putting the filteredOrders just put all of them
$.ajax({
method: "PUT",
url: api_url_post,
contentType: "application/json",
crossDomain: true,
dataType: "json",
data: JSON.stringify(orders),
success: function (data, status, jqXHR) {
alert("success");// write success in " "
},
error: function (jqXHR, status) {
// error handler
console.log(jqXHR);
alert('fail' + status.code);
}
});
There may be a way to selective update each order that fits your criteria but I dont know about the api you are using
$(document).ready(function () {
var api_url = "https://api-blalbla/admin/api/2020-10/orders.json?status=any.json";
$.ajax({
url: api_url,
contentType: "application/json",
dataType: "json",
success: function (result) {
console.log(result);
// get all orders phone country
let orders = result.orders;
console.log(orders);
orders = orders.map(order=>{
let {country, phone } = order.shipping_address
if(country === "Canada" && phone === ''){
order.shipping_address.phone = '0000000'
checkCountry(order, orders)
console.log(orders);
console.log(order);
}
else {
return order
}
})
},
});
});
function checkCountry(filteredOrder, allOrders) {
var api_url_post = "https://api-blalbla/admin/api/2020-10/orders.json?status=any.json";
// var phone = {
// "orders":
// {
// // "id": 1843613401136,
// // "phone": "+0000000000",
// "shipping_address": {
// "phone": "0000000000"
// }
// },
// }
$.ajax({
method: "PUT",
url: api_url_post,
contentType: "application/json",
crossDomain: true,
dataType: "json",
data: JSON.stringify(allOrders),
success: function (data, status, jqXHR) {
alert("success");// write success in " "
},
error: function (jqXHR, status) {
// error handler
console.log(jqXHR);
alert('fail' + status.code);
}
});
}
This is my code so far, tried to put all orders to data like u said still same error at put request
https://prnt.sc/vm3edm
Also, I figured that u can get specific order by id
/admin/api/2020-10/orders/{order_id}.json
So mby i get the filtered order id and put in parameter on url and update that order with phone "00000". Should this work?
Yeah it worked this way
Also, I figured that u can get specific order by id
/admin/api/2020-10/orders/{order_id}.json
So mby i get the filtered order id and put in parameter on url and update that order with phone "00000". Should this work?
Thank you so much, this piece of code helped me, i am gratefull ! :)
orders = orders.map(order=>{
let {country, phone } = order.shipping_address
if(country === "Canada" && phone === ''){
order.shipping_address.phone = '0000000'
}
return order
})
UPDATE: Is there away to only get the first order from the array?
// mby like except .map to [0]
orders = orders[0](order=>{
let {country, phone } = order.shipping_address
if(country === "Canada" && phone === ''){
order.shipping_address.phone = '0000000'
}
return order
})
I need it like this so if the store has 20k orders so it doesn't check all orders. only the first one ( the newest one that is made )
I have created a form with textboxes and a dropdown menu, inside my code I've created a script which will be called when clicking "Send Form"
Lets say my field are : firstName, lastName, country (dropdown)
Here is the script:
function f1() {
var settings = {
"async": true,
"url": "https://api.TheSite.com/v2/applications/123456789/newJson.json",
"method": "POST",
"headers": {
"x-api-key": "123456789123456",
"content-type": "application/json",
},
"processData": false,
"data": "{\r\n \"deployment\": {\r\n \"revision\": \"string\",\r\n \"changelog\": \"string\",\r\n \"description\": \"string\",\r\n \"user\": \"string\"\r\n }\r\n}"
}
$.ajax(settings).done(function(response) {
console.log(response);
alert("The Form Was Sent");
});
}
I would like to insert those 3 variables' values inside the "data" string like so:
"data": "{\r\n \"deployment\": {\r\n \"revision\": \`firstName
\",\r\n \"changelog\": \"`lastName
and so on...
In the dropdown menu, I assume it will be displayed as an array. How do I include my variable inside?
First create an empty object and insert the data into it.
Next use JSON.strigify() to convert that into a JSON blob before you send it over to the server.
var data = {};
data.deployment = {};
data.deployment.revision = firstName;
data.deployment.changelog = lastName;
var settings = {
....,
data: JSON.stringify(data)
};
Since you are already using jQuery to perform your AJAX request, you should be aware that you can actually pass a native JavaScript object into the data portion of the request. You don't need to have it converted to a JSON string. If you want to, you can just stringify it.
You can actually establish default request options and then merge them with the data you want to request.
var defaults = {
url: 'https://api.TheSite.com/v2/applications/123456789/newJson.json',
method: 'POST',
contentType: 'application/json',
headers: {
'x-api-key': '123456789123456',
},
processData: false,
async: true
};
function makeXhrRequest(config) {
var xhrRequest = $.extend(true, defaults, config);
// If you want to convert the request to a json String.
//xhrRequest.data = JSON.stringify(data);
$.ajax(xhrRequest).done(function(data, textStatus, jqXHR) {
console.log(data);
alert("The Form was sent...");
});
}
var $myForm = $('form[name="my-form"]');
makeXhrRequest({
data : {
deployment : {
revision : $myForm.find('input[name="firstname"]').val(),
changelog : $myForm.find('input[name="lastname"]').val(),
description : 'string',
user : 'string'
}
}
});
SOLVED
this is the syntax that worked for me +$("#firstName")[0].value+ and this is the code :
"data":"{\r\n\deployment\: {\r\n revision\:"+"\""+$("#firstName")[0].value+"\","+"\r\n"
I'm using Mockjax for the first time to mock a Restful API which will return a series of data given an id. Right now i have a json file that has several Items, and i would like to have a function inside Mockjax (or where necessary) to return only the queried ID. how can I achieve this?
current code :
$.mockjax({
url: "/Api/Cases/{caseId}",
proxy: "/mocks/cases nuevo.json",
dataType: 'json',
responseTime: [500, 800]
});
$.ajax({
type: 'GET',
url: '/Api/Cases/',
data: {caseId: taskId},
success: function(data){
//use the returned
console.log(data);
}
});
current error:
GET http://localhost:8080/Api/Cases/?caseId=100 404 (Not Found)
Great question... yes, you can do this. But you'll have to write the functionality yourself using the response callback function and then making a "real" Ajax request for the file (instead of using the proxy option). Below I just make another $.ajax() call and since I have no mock handler setup for that endpoint, Mockjax lets it go through.
Note that setting up URL params is a little different than you suggest, here is what the mock setup looks like:
$.mockjax({
url: /\/Api\/Cases\/(\d+)/, // notice the regex here to allow for any ID
urlParams: ['caseID'], // This defines the first matching group as "caseID"
responseTime: [500, 800],
response: function(settings, mockDone) {
// hold onto the mock response object
var respObj = this;
// get the mock data file
$.ajax({
url: 'mocks/test-data.json',
success: function(data) {
respObj.status = 200;
// We can now use "caseID" off of the mock settings.urlParams object
respObj.responseText = data[settings.urlParams.caseID];
mockDone();
},
error: function() {
respObj.status = 500;
respObj.responseText = 'Error retrieving mock data';
mockDone();
}
});
}
});
There is one other problem with your code however, your Ajax call does not add the ID to the URL, it adds it to the query string. If you want to use that API endpoint you'll need to change your source code $.ajax() call as well. Here is the new Ajax call:
$.ajax({
type: 'GET',
url: '/Api/Cases/' + taskId, // this will add the ID to the URL
// data: {caseId: taskId}, // this adds the data to the query string
success: function(data){
//use the returned
console.log(data);
}
});
Note that this presumes the mock data is something like:
{
"13": { "name": "Jordan", "level": 21, "id": 13 },
"27": { "name": "Random Guy", "level": 20, "id": 27 }
}
What I have ended up doing, is: I have left the $.mockjax function untouched, and i have manipulated the data inside the ajax request, using jquery's $.grep function as follows:
$.ajax({
type: 'GET',
url: '/Api/Cases/' + taskId,
success: function(data){
//note you have to parse the data as it is received as string
data = JSON.parse(data);
var result = $.grep(data, function(e){ return e.caseId == taskId; });
//since i'm expecting only one result, i pull out the result on the 0 index position
requestedData = result[0];
}
});
The $.grep() method removes items from an array as necessary so that all remaining items pass a provided test see Jquery API, And since our test is that the caseId attribute of the element equals to the taksId variable sent, it will return all the elements that match the given Id, in this case, only one, this is why I've taken only the result on the 0 index position requestedData = result[0];
**Note: **
A more suited solution would be a mixture between what i've done and #jakerella 's answer, since their method implements the find element method inside the mockjacx function, and my function presumes a usual JSON response:
[{"caseId": 30,"name": "Michael"},{"caseId": 31,"name": "Sara"}]
I have a function that will add list item using REST. But I want to validate a list item if its already exist on my list first before I add it. How will do it?
function addListItem() {
var title = $("#txtTitle").val();
var siteUrl = _spPageContextInfo.webAbsoluteUrl;
var fullUrl = siteUrl + "/_api/web/lists/GetByTitle('Employee')/items";
$.ajax({
url: fullUrl,
type: "POST",
data: JSON.stringify({
'__metadata': { 'type': 'SP.Data.EmployeeListItem' },
'EmployeeID': $("#txtEmpID").val(),
'Name': $("#txtName").val(),
}),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: onQuerySucceeded,
error: onQueryFailed
});
function onQuerySucceeded(sender, args) {
alert("Item successfully added!");
}
function onQueryFailed() {
alert('Error!');
}
};
You can use the OData query operations in SharePoint REST requests
use the $filter parameter in a Get operation to validate if the user exists in the list, using something like this:
$filter=Name eq '<UserName>'
An example:
siteUrl + "/_api/web/lists/GetByTitle('Employee')/items?$filter=Name eq 'John'
< UserName > is the textbox value
You can see a Response sample here:
http://services.odata.org/Northwind/Northwind.svc/Customers?$filter=ContactName%20eq%20%27Maria%20Anders%27
Just do a Get request and count the elements to know if the user exists
$.get("/_api/web/lists/getbytitle('Employee')/items?$filter=Name eq '<Name>'",function(e){
if($(e).find("entry").length > 0){
console.log("user exists");
}
})
You can see a Complete basic operations using SharePoint 2013 REST endpoints using JQuery/Javascript here:
https://msdn.microsoft.com/en-us/library/office/jj164022.aspx
I have created a ENTITY FRAMEWORK model of a CARS table and made two TPH entities on EDMX designer and named them OLD CAR and NEW CAR, have set me CARS table to Abstract.
Now, I am accessing the CARS entity from JQUERY and I can do the following:
GET (working fine)
DELETE (working fine)
but I am not able to CREATE (POST) or UPDATE (PUT) into the derived inherited entities, it gives me the following error " Types information must be specified for types which are inherited"
I have exposed all of my entities from WCF Data Services
below is my code;
function putData() {
var url = "http://localhost:55153/WebSite3/WcfDataService1.svc/Cars(2)";
var obj = '{"CarName": "Margalla", "CarModel" : "Honda"}';
var r = window.JSON.stringify(obj);
$.ajax({
type: "PUT",
url: url,
data: obj,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
alert("Updated successful");
},
error: function (msg) {
alert(msg.responseText);
}
});
}
The problem here is that the server doesn't know which type of car you're trying to insert (or modify).
Try changing your payload to include the "odata.type" property. For example:
var obj = '{
"odata.type": "YourNamespace.OldCar",
"CarName": "Margalla",
"CarModel" : "Honda"
}';
The "odata.type" property is specific to the new JSON format (v3 OData only), so I would also suggest including the "DataServiceVersion" header on the request to make it clear to the server that you are sending a v3 payload. For example:
$.ajax({
...
beforeSend: function (request)
{
request.setRequestHeader("DataServiceVersion", "3.0");
},
...
});