Rest API Multiple Lists in SharePoint - javascript

Because SharePoint works async i cannot store the data from multiple lists in array's and access them later.
I need to use 3 lists because they contain data from employees, holidays, and more.
See my code below for more information.
Is there no easier way to work with SharePoint and multiple lists to get the data. I tried also with executequeryasync but i cannot find a working solution for multiple lists. Or to store the value of each list in an array or variable and use it in another function because it's async.
$(function () {
$('#title').html("Inloggen verlofaanvraag");
});
function inLoggen() {
var initialen = $('#initialen').val();
var wachtwoord = $('#wachtwoord').val();
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Lijst werknemers')/Items?$filter=wInitialen eq '" + initialen + "' and wWachtwoord eq '" + wachtwoord + "'",
type: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
var x = data.d.results;
var werknemers = data.d.results;
for (var i = 0; i < x.length; i++) {
rInitialen = x[i].wInitialen;
rWachtwoord = x[i].wWachtwoord;
rVolledigenaam = x[i].wVolledigenaam;
}
if (i === 0) {
alert("U hebt geen toegang tot deze pagina !");
}
else {
$('#title').html("Welkom " + rVolledigenaam);
$('#inlogform').hide();
persoonlijketellers(werknemers);
}
},
error: function (xhr) {
console.log(xhr.status + ': ' + xhr.statusText);
}
});
}
function persoonlijketellers(werknemers) {
var rId = werknemers[0].ID;
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Lijst persoonlijke tellers')/Items?$filter=pWerknemer eq '" + rId + "'",
type: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
var x = data.d.results;
var ptellers = data.d.results;
for (var i = 0; i < x.length; i++) {
}
wettelijkeverlofdagen(werknemers, ptellers);
},
error: function (xhr) {
console.log(xhr.status + ': ' + xhr.statusText);
}
});
}
function wettelijkeverlofdagen(werknemers, ptellers) {
var rId = ptellers[0].ID;
alert(rId);
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Lijst persoonlijke tellers')/Items?$filter=pWerknemer eq '" + rId + "'",
type: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
var x = data.d.results;
var ptellers = data.d.results;
for (var i = 0; i < x.length; i++) {
}
},
error: function (xhr) {
console.log(xhr.status + ': ' + xhr.statusText);
}
});
}

You can store the data from multiple lists in array and access them when all of your async calls are complete, you just need to use some sort of promise pattern.
jQuery's .when method is probably the most useful in a situation like this:
function SPData() {
function getJsonDataAsync(url) {
// returning the $.ajax object is what makes the next part work...
return $.ajax({
url: url,
method: "GET",
contentType: "application/json",
headers: {
accept: "application/json;odata=verbose"
}
});
}
var requestURI1 = _spPageContextInfo.webServerRelativeUrl + "/_api/lists/..."
var requestURI2 = _spPageContextInfo.webServerRelativeUrl + "/_api/lists/..."
var requestURI3 = _spPageContextInfo.webServerRelativeUrl + "/_api/lists/..."
var req1 = getJsonDataAsync(requestURI1);
var req2 = getJsonDataAsync(requestURI2);
var req3 = getJsonDataAsync(requestURI3);
// now we can do the next line, because req1/2/3 are actually deferreds
// being returned from $.ajax
jQuery.when(req1, req2, req3).done(function(resp1, resp2, resp3) {
/* do something with all of the requests here...
resp1/2/3 correspond to the responses from each call and are each an
array that looks like: [data, statusText, jqXHR], which means that your
data is in resp1[0], resp2[0], etc. */
});
If you want, you can also just assign the returned values to variables in a higher level context, then use individual jQuery deferreds so that you can be sure all of the calls have succeeded before you start working with the data...
...
var x1, x2, x3;
// use the .then(function() { ... }) pattern because we are just returning a
// deferred/promise from $.ajax
getJsonDataAsync(requestURI1).then(function(data) {
x1 = data;
getJsonDataAsync(requestURI2).then(function(data2) {
x2 = data2;
getJsonDataAsync(requestURI3).then(function(data3) {
x3 = data3;
// do something with x1, x2, and x3
});
});
});
}

Related

Trying to get current user of SharePoint Page

Trying to get the user of a html page that resides in a SP document library. I tried doing something similar what is in this SO post but getting undefined. How can I get the user currently on the page? Thank you.
The function where I am trying to get the current user is $scope.updateTicket()
Below is the all of the JS code.
var app = angular.module('myApp', []);
var reports = [];
var areports = [];
var breports = [];
app.controller('myController',
function($scope, $http) {
$http({
method: 'GET',
url: ".../_api/web/lists/GetByTitle('tickets')/items?$top=1000&$select=ID,comments,ticket_number,status,date",
headers: {"Accept": "application/json;odata=verbose"}
}).success(function (data, status, headers, config) {
$scope.reports = data.d.results;
$scope.openModal = function() {
$getFormDigest = function() {
console.log("Inside getFormDigest...");
var formdigest;
jQuery.ajax({
url: "..._api/contextinfo",
type: "POST",
async: false,
headers: {
"accept": "application/json; odata=verbose",
type: "POST"
},
success: function(data)
{
formdigest = data.d.GetContextWebInformation.FormDigestValue
}
});
return formdigest;
}
$scope.updateFunc = function(itemID, new_comment) {
console.log('In update function...', itemID);
var formdigest = $scope.getFormDigest();
jQuery.ajax({
url: ".../_api/web/lists/GetByTitle('tickets')/items(" + itemID + ")",
type: "POST",
data: JSON.stringify({
'__metadata': { 'type': 'SP.Data.ticketsListItem' },
'comments': new_comment
}),
headers: {
"accept" : "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": formdigest,
"IF-MATCH": "*",
"X-HTTP-Method": "MERGE"
},
success: function(data)
{
console.log("comments updated successfully...");
},
error: function(data)
{
console.log($("#__REQUESTDIGEST").val());
console.log("Error message: " + JSON.stringify(dta.responseJSON.error));
}
});
}
$scope.updateTicket = function() {
jQuery.ajax({
url: ".../_api/web/currentuser?select=Title",
type: "GET",
success: function(data)
{
var title = data.d.Title;
console.log(title);
},
error: function(data) {
console.log("Error occurred trying to get user Title");
}
});
var submitter = document.getElementById("submitter");
var context = SP.ClientContext.get_current();
var web = context.get_web();
var user = context.get_web().get_currentUser();
context.load(user);
console.log("User: " + web.get_currentUser().$5_0.$H_0.Title);
//var submitter = web.get_currentUser().$5_0.$H_0.Title;
var now = new Date();
var timestamp = (now.getUTCMonth() + 1 + "/" + now.getUTCDate() + "/" + now.getFullYear() + " " + ("0" + now.getUTCHours()).slice(-2) + ":" ("0" + now.getUTCMinutes()).slice(-2));
var temp = document.getElementById('comments').innerHTML;
temp += '<br>' + timestamp + ' -- ' + submitter + '<br>' + document.getElementById('comment-field').value + '<br>';
document.getElementById('comments').innerHTML = '<br>' + temp + '<br>';
$scope.updateFunc(document.getElementById('id').innerHTML, temp);
document.getElementById('comment-field').value = '';
document.getElementById('myModal').style.display = 'none';
location.reload();
};
modal.display = "block";
};
}).error(function(data, status, headers, config) {
console.log("an error occurred...");
});
var modal = document.getElementById('myModal');
var span = document.getElementByClassName("close")[0];
span.onclick = function() {
modal.style.display = "none";
}
window.onclick = function(event) {
if(event.target == modal) {
modal.style.display = "none";
}
}
});
In the head of my HTML file I'm pulling in the following SP libraries
init.js
MicrosoftAjax.js
sp.core.js
sp.runtime.js
sp.js
if we are talking about SharePoint OnPrem then You may always use _spPageContextInfo object which have many information about current context. In this object You also have the current user id and login in userId prop and userLoginName prop
Yep _spPageContextInfo.userDisplayName is all you need:
_spPageContextInfo.userDisplayName
_spPageContextInfo.userEmail
_spPageContextInfo.userId
_spPageContextInfo.isSiteAdmin

Removing div based on the ID not existing in a jQuery AJAX response

I am getting rows of content via jQuery AJAX and then populating the table with new content as it is being added. The problem is that some content may be deleted from the database, in which case I also want it removed in real-time from the table.
I suspect I need to loop through the table div IDs and remove any IDs that don't exist in the AJAX response but I'm unsure how to compare them to the data response and then remove them:
function startRecords() {
$.ajax({
url: URL,
dataType: 'json',
success: function(data) {
var res = data;
for (var i = 0, len = res.length; i < len; i++) {
if ($("#records-row-" + res[i].id).length == 0) {
$("#records-content tbody").prepend('<tr class="table-wrapper" id="records-row-' + res[i].id + '"><td class"" style="">' + res[i].content_1 + '</td><td class"" style="">' + res[i].content_2 + '</td></tr>');
}
}
var delay = 3000;
setTimeout(function() {
startRecords();
}, delay);
},
cache: false
}).fail(function(jqXHR, textStatus, error) {
var delay = 3000;
setTimeout(function() {
startRecords();
}, delay);
});
}
Any recommendations on how to achieve this?
you are prepending to "records-content" div without clearing it first.
you need to add
$("#records-content tbody").html('')
before starting your for loop.
this way only current data in you database table will populate in table.
Use empty() to clear the records, before prepending new ones.
function startRecords() {
$.ajax({
url: URL,
dataType: 'json',
success: function(res) {
$("#records-content tbody").empty();
for (var i = 0, len = res.length; i < len; i++) {
if ($("#records-row-" + res[i].id).length == 0) {
$("#records-content tbody").prepend('<tr class="table-wrapper" id="records-row-' + res[i].id + '"><td class"" style="">' + res[i].content_1 + '</td><td class"" style="">' + res[i].content_2 + '</td></tr>');
}
}
var delay = 3000;
setTimeout(function() {
startRecords();
}, delay);
},
cache: false
}).fail(function(jqXHR, textStatus, error) {
var delay = 3000;
setTimeout(function() {
startRecords();
}, delay);
});
}
To remove elements that are not in the response from server.
Add the following right after success: function(res) {
var currentRows = $("[id^=records-row-]").toArray()
var currentRowsId = currentRows.map(function(row) { return row.id })
var resRows = res.map(function(row) { return "records-row-" + row.id })
var removeRows = currentRowsId.filter(function(rowId) { return resRows.indexOf(rowId) === -1 })
removeRows.forEach(function(rowId) { $("#" + rowId).remove() })
So that it looks like this
function startRecords() {
$.ajax({
url: URL,
dataType: 'json',
success: function(res) {
var currentRows = $("[id^=records-row-]").toArray()
var currentRowsId = currentRows.map(function(row) { return row.id })
var resRows = res.map(function(row) { return "records-row-" + row.id })
var removeRows = currentRowsId.filter(function(rowId) { return resRows.indexOf(rowId) === -1 })
removeRows.forEach(function(rowId) { $("#" + rowId).remove() })
for (var i = 0, len = res.length; i < len; i++) {
if ($("#records-row-" + res[i].id).length == 0) {
$("#records-content tbody").prepend('<tr class="table-wrapper" id="records-row-' + res[i].id + '"><td class"" style="">' + res[i].content_1 + '</td><td class"" style="">' + res[i].content_2 + '</td></tr>');
}
}
var delay = 3000;
setTimeout(function() {
startRecords();
}, delay);
},
cache: false
}).fail(function(jqXHR, textStatus, error) {
var delay = 3000;
setTimeout(function() {
startRecords();
}, delay);
});
}
With comments
var currentRows = $("[id^=records-row-]").toArray() // get rows with id starting with "records-row-"
var currentRowsId = currentRows.map(function(row) { return row.id }) // extract ids from rows
var resRowsId = res.map(function(row) { return "records-row-" + row.id }) // extract ids from response that will be added to DOM
var removeRows = currentRowsId.filter(function(rowId) { return resRowsId.indexOf(rowId) === -1 }) // remove every element that is added to DOM and in response from server
removeRows.forEach(function(rowId) { $("#" + rowId).remove() }) // remove elements that are not in response and is added to DOM
Alternative solution
$("#records-content tbody").empty(); to remove every element each time the client fetches new data from server.

object doesn't support this property or method using AJAX

Please see the code below:
$.ajax({
type: "POST",
url: "Results1.aspx/TableQuery",
data: JSON.stringify({
mappingid: res[i],
strCon: $("#fieldGenieConnectionString")[0].value,
strTypeSession: $("#fieldTypeSession")[0].value
}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: OnSuccess(i, res.length),
error: OnError,
failure: function (response) {
alert('there was a failure loading the webpage')
}
});
and the code below:
function OnSuccess(i, totalrows) {
return function (response) {
//if (response.d != "") {
var strResponse = response.d;
strResponse = strResponse.toUpperCase;
if (strResponse.indexOf("<TR>") > 0) {
// alert(response.d);
document.getElementById('div' + i).innerHTML = document.getElementById('div' + i).innerHTML + '<br>' + '<br>' + response.d;
}
numSucceeded++;
var completeCalculation = (numSucceeded / totalrows) * 100
var rounded = completeCalculation.toFixed(0);
document.getElementById('ProgressIndicator').innerHTML = rounded + ' % complete';
document.getElementById('ProgressIndicator2').innerHTML = rounded + ' % complete';
if (numSucceeded === totalrows) {
var end = new Date().getTime();
var htmlResponse = "Loaded after: " + (end - start) / 1000 + " seconds"
document.getElementById('TotalTimeLabel').innerHTML = htmlResponse;
document.getElementById('TotalTime2Label').innerHTML = htmlResponse;
$("#LoadingImage").hide();
$("#LoadingImage2").hide();
}
}
}
The following line causes an error:
if (strResponse.indexOf("<TR>") > 0) {
strResponse = strResponse.toUpperCase;
There is a typo here. I think you want to write strResponse = strResponse.toUpperCase();
You are assigning a function to strResponse instead of calling the toUpperCase() on the existing strResponse

using 'GetGlobalContext' in javascript web resource

I'm creating a custom button in the MS CRM ribbon that create a record in an entity, (i'm using odata), this button lunch a JavaScript function that use 'GetGlobalContext' method to get the context, im facing the below problem:
The value of the property 'GetGlobalContext' is null or undefined
here is my sample code :
//Parameters
var ODataPath;
var serverUrl;
//add the below script to the page DOM
var imported = document.createElement('script');
imported.src = 'ClientGlobalContext.js.aspx';
document.getElementsByTagName('head')[0].appendChild(imported);
//On COnvert to case click
function OnConvertClick(message) {
alert(Xrm.Page.getAttribute(message).getValue());
var data = {
subject: Xrm.Page.getAttribute(message).getValue()
};
CreateCaseOffer("incident", data);
}
//create case from an activity
function CreateCaseOffer(EntityName, data) {
var context = GetGlobalContext(); //GetGlobalContext function exists in ClientGlobalContext.js.aspx
serverUrl = location.protocol + "//" + location.hostname + ":" + location.port + "/" + context.getOrgUniqueName();
ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";
var jsonCaseOffers = window.JSON.stringify(data);
if (jsonCaseOffers != null) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: ODataPath + "/" + EntityName + "Set",
data: jsonCaseOffers,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
success: function (data, textStatus, XmlHttpRequest) {
$.each(data, function (k, v) {
alert(k + " - " + v);
});
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
}
});
}
}
any suggestions ??
it works fine now with var
var context = Xrm.Page.context;
instead of
var context = GetGlobalContext();

Changing global variables in a ajax call

I've been trying to get this right for quite some time, I'm trying to append the object from the first ajax call after the second ajax call. But the for loop seems to iterate the changing of the value to the last result before appending the information, having the last post appended every time.
var scribjson =
{
"user_id" : localStorage.viewing,
};
scribjs = JSON.stringify(scribjson);
var scrib = {json:scribjs};
$.ajax({
type: "POST",
url: "getScribbles.php",
data: scrib,
success: function(result)
{
var obj = jQuery.parseJSON(result);
for(var i = 0; i < obj.length; i+=1)
{
var userjson =
{
"user_id" : obj[i].user_id
};
userjs = JSON.stringify(userjson);
var user = {json:userjs};
localStorage.post = obj[i].post;
$.ajax({
type: "POST",
url: "getRequestsInfo.php",
data: user,
success: function(result)
{
var obj2 = jQuery.parseJSON(result);
$('#listOfScribbles').append("<tr><td><img id = 'small_pic' src = '" + obj2[0].profileImage + "'/></td><tr><td>" + obj2[0].firstname + " " + obj2[0].lastname + "</td></tr> ");
$('#listOfScribbles').append("<tr><td>" + obj[i].post + "</td></tr>");
},
error: function()
{
alert('An Error has occured, please try again.');
}
});
}
},
error: function()
{
alert('An Error has occured, please try again.');
}
});
Since ajax calls It looks like the all success functions of the inner ajax call are being called after the loop has ended, so i will always be the last iterated value.
Try this:
(function(i)
{
$.ajax({
type: "POST",
url: "getRequestsInfo.php",
data: user,
success: function(result)
{
var obj2 = jQuery.parseJSON(result);
$('#listOfScribbles').append("<tr><td><img id = 'small_pic' src = '" + obj2[0].profileImage + "'/></td><tr><td>" + obj2[0].firstname + " " + obj2[0].lastname + "</td></tr> ");
$('#listOfScribbles').append("<tr><td>" + obj[i].post + "</td></tr>");
},
error: function()
{
alert('An Error has occured, please try again.');
}
});
})(i);
This will create a closure on i, which will give each ajax call its own copy of the current value.
Use an IIFE:
success: (function(i){return function(result) {
var obj2 = jQuery.parseJSON(result);
$('#listOfScribbles').append("<tr><td><img id = 'small_pic' src = '" + obj2[0].profileImage + "'/></td><tr><td>" + obj2[0].firstname + " " + obj2[0].lastname + "</td></tr> ");
$('#listOfScribbles').append("<tr><td>" + obj[i].post + "</td></tr>");
}})(i),
etc. Currently your loop generated ajax success handlers contain a direct reference to the counter itself, which (by the time they are called) has reached its final value.

Categories