How to access value outside of forEach in jquery - javascript

GetMandatoryFieldsforUser: function (data) {
var field = [];
$.get("api/mapping/mandatoryfield?type=USER", function (data) {
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field) //able to print value
})
console.log(field) // not able to print value
return MandatoryFields.User;
},
EDIT
MandatoryFields = {
User: field,
}
my question here is i need to access field value outside forEach loop.How to achieve this using jquery or javascript
EDIT
"api/mapping/mandatoryfield?type=USER" returns
["First Name", "Last Name", "Location", "Email", "Password"],
see the edited question i want to use that field array inside MandatoryFields.User but if i use it its not showing the value

This implements $.ajax:
GetMandatoryFieldsforUser: function (data) {
var field = [];
$.ajax({
url: "api/mapping/mandatoryfield?type=USER"
}).done(function(data) {
// THIS PORTION IS EXECUTED AFTER DATA IS LOADED
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field)
/*
USE return HERE!
*/
return field; // OR SOMETHING ELSE
})
// THIS WON'T WORK, BECAUSE DATA IS RETRIEVED IN ASYNC!
console.log(field)
},

Since $.get() is an asynchronous method, you can use async/await to access the returned value from the $.get method's callback.
GetMandatoryFieldsforUser: async function (data) {
var field = [];
const returnedField = await $.get("api/mapping/mandatoryfield?type=USER", function (data) {
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field) //able to print value
return field;
}).promise()
console.log(returnedField) // not able to print value
},

You should use the ajax method in jquery.
function GetMandatoryFieldsforUser( data)
{
var field= [];
var scriptUrl = "api/mapping/mandatoryfield?type=USER";
$.ajax({
url: scriptUrl,
type: 'get',
dataType: 'html',
async: true,
success: function(data) {
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field)
}
});
return field;
}

Related

Accessing a global variable that is been updated from an asynchronous function

i'm really struggling to understand the asynchronous side of JavaScript. the code i have is meant to collate specific details of certain users and then put all the collated information into a global variable array which i intent to manipulate when all the users have been added to the array. i'm finding it difficult to iterate the array because when i do an array.length on the printurlonPage() function i get a 0 despite the fact that when i do a console log on the array itself i can see that there are items there. Does anyone know a technique that allows me to work on the global variable only after the asynchronous function has completed?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
var PeopleCompleteList = [];
function PersonConstructor(username,Title,Phone,Email,imageurl){
return {
name: username,
Title: Title,
phoneNumber: Phone,
Email: Email,
Picture: imageurl
}
}
var printurlonPage = function (){
for (var link in PeopleCompleteList) {
console.log(link['Picture']);
}
console.log(PeopleCompleteList);
}
var getIndividualPersonDetails = function(GetPictureUrl) {
listName = 'TeamInfo';
//var PeopleCompleteList = [];
// execute AJAX request
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('"+listName+"')/items?$select=Name/Title,Name/Name,Name/Id,Name/EMail,Name/WorkPhone&$expand=Name/Id",
type: "GET",
headers: { "ACCEPT": "application/json;odata=verbose" },
success: function (data) {
for (i=0; i< data.d.results.length; i++) {
//check if the user exists if he does store the following properties name,title,workphone,email and picture url
if(data.d.results[i]['Name'] != null){
var personName = data.d.results[i]['Name'].Name.split('|')[2];
var userName = data.d.results[i]['Name']['Name'];
var UserTitle = data.d.results[i]['Name']['Title'];
var UserphoneNumber = data.d.results[i]['Name']['WorkPhone'];
var UserEmail = data.d.results[i]['Name']['EMail'];
var myuserPicture = GetPictureUrl(userName);
console.log(myuserPicture);
PeopleCompleteList.push(PersonConstructor(personName, UserTitle, UserphoneNumber,UserEmail,myuserPicture));
}
}
},
error: function () {
alert("Failed to get details");
}
});
}
function GetPictureUrl(user) {
var userPicture="";
var requestUri = _spPageContextInfo.webAbsoluteUrl +
"/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=#v)?#v='"+encodeURIComponent(user)+"'";
$.ajax({
url: requestUri,
type: "GET",
async:false,
headers: { "ACCEPT": "application/json;odata=verbose" },
success: function (data) {
console.log(data);
var PictureDetails = data.d.PictureUrl != null ? data.d.PictureUrl : 'c:\apps\noimageurl.jpg';
userPicture=PictureDetails;
}
});
return userPicture;
};
$(function () {
getIndividualPersonDetails(GetPictureUrl);
printurlonPage();
});
</script>
You're printurlonPage() is not asynchronous, so it's running before getIndividualPersonDetails responds. You can do two things, use promises or use async/await from es7. I prefer async/await, but you'll need to babelify.
Or, you can just put your printurlonPage invocation inside your success: handler.
success: function (data) {
for (i=0; i< data.d.results.length; i++) {
//check if the user exists if he does store the following properties name,title,workphone,email and picture url
if(data.d.results[i]['Name'] != null){
var personName = data.d.results[i]['Name'].Name.split('|')[2];
var userName = data.d.results[i]['Name']['Name'];
var UserTitle = data.d.results[i]['Name']['Title'];
var UserphoneNumber = data.d.results[i]['Name']['WorkPhone'];
var UserEmail = data.d.results[i]['Name']['EMail'];
var myuserPicture = GetPictureUrl(userName);
console.log(myuserPicture);
PeopleCompleteList.push(PersonConstructor(personName, UserTitle, UserphoneNumber,UserEmail,myuserPicture));
}
}
printurlonPage();
},
And then in document.ready:
$(function () {
getIndividualPersonDetails(GetPictureUrl);
});
So, getIndividualPersonDetails is invoked, and then when it receives the data, the callback is invoked with the data.

How to filter JSON data for autosuggestion using Ajax (without jQuery ui)

I am trying to create an auto-suggestion from scratch. I am using canjs controller to control the DOM elements (ul and li).
I want smart and short code to implement this. I have tried with filter but I want Ajax filter method to use for this purpose.
I have tried the following thing:
can.Model:
var SearchDomainModel = can.Model.extend({
findAll: function(){
return this.getDomains;
}
}, { domainList: null,
getDomains: function(params, callback) {
var promise = $.ajax({
url: '/scripts/models/domains.json',
type: 'GET',
dataType: 'json',
dataFilter: function(data, type){
var parsed_data = JSON.parse(data);
var regex = new RegExp(params, 'gi')
var temp = [];
$.each(parsed_data, function(i, item){
for(var j in item)
if ((item[j].url).toLowerCase().indexOf(params) >= 0){
temp.push(item[j].url);
console.log(temp);
}
});
return temp;
}
});
This is my can.controller:
var DomainController = can.Control.extend({
defaults: {
view: 'views/domainSearch.hbs'
}
}, {
searchList: new can.List(),
domainModel: new DomainModel(),
init: function(element, options) {
this.element.html(can.view(this.options.view, this.searchList));
$('html,body').css({
percentWidth: 100,
percentHeight: 100
});
$('.error').hide();
}, // control domain filter on keyup event
'input keyup': function(element, event) {
var self = this;
var searchText = element.val();
if (searchText !== "") {
this.domainModel.getDomains(searchText, function (response, error) {
self.searchList.attr("domains",response);
console.log(error);
})
I am trying and searching from last two days. I could not have done it. Can anybody suggest me where is my mistake in the code and how to solve it?
Thanx in advance!!
I would probably do something like this:
var SearchDomainModel = can.Model.extend({
findAll: function(){
return this.getDomains;
}
}, { domainList: null,
getDomains: (function() {
var domains = null;
function search(searchText, callback){
var regex = new RegExp(searchText, 'gi')
var temp = [];
$.each(domains, function(i, item){
for(var j in item)
if (regex.test(item[j].url))
temp.push(item[j].url);
});
callback(temp);
}
return function(searchText, callback) {
if( domains ) {
search(searchText, callback);
return;
}
$.ajax({
url: '/scripts/models/domains.json',
type: 'GET',
dataType: 'json',
success: function(data) {
domains = data;
search(searchText, callback);
}
});
};
})()
});
I didn't test the code but it doesn't spawn one ajax request everytime you release a key but instead grabs the data once and then refers to the same data.

Passing/returning value to/from a function using ajax and callback function

I'm trying to read p_info array returned from the function getproductInfo containing a ajax call but I'm getting undefined value. I'm using a callback function to achieve this but still doesn't work. Where am I wrong?
$(document).ready(function() {
function successCallback(data)
{
var name = data.name;
var image = data.image;
var link = data.link;
var product_info = [name, image, link];
console.log(product_info); // Correct: shows my product_info array
return product_info;
}
function getProductInfo(prodId, successCallback) {
$.ajax({
type: "POST",
url: "getProductInfo.php",
data: "id=" + prodId,
dataType: "json",
success: function(data) {
var p_info = successCallback(data);
console.log(p_info); // Correct: shows my product_info array
return p_info;
},
error: function()
{
alert("Error getProductInfo()...");
}
});
return p_info; // Wrong: shows "undefined" value
}
var p_info = getProductInfo(12, successCallback);
console.log(p_info); // Wrong: shows an empty value
});
The code should speak for itself. But basically, you cant return an upper-level function inside a function. You must set a variable to be used to return after the ajax is submitted.
//This makes the p_info global scope. So entire DOM (all functions) can use it.
var p_info = '';
//same as you did before
function successCallback(data) {
var name = data.name;
var image = data.image;
var link = data.link;
var product_info = [name, image, link];
return product_info;
}
//This takes prodID and returns the data.
function getProductInfo(prodId) {
//sets up the link with the data allready in it.
var link = 'getProductInfo.php?id=' + prodId;
//creates a temp variable above the scope of the ajax
var temp = '';
//uses shorthand ajax call
$.post(link, function (data) {
//sets the temp variable to the data
temp = successCallback(data);
});
//returns the data outside the scope of the .post
return temp;
}
//calls on initiates.
var p_info = getProductInfo(12);
console.log(p_info);

jQuery Ajax Race Condition best practice

In a button.click(function(){}); I have the following code:
var userId = $("#user-permission-edit").val();
var peId = $("#user-permission-entity-list").val();
var newParentPEId = $("#new-parent-pe").val();
var newPeName = $("#pe-name-add").val();
$.ajax({
type: "POST",
url: 'AddNewPE',
data: { 'targetUserId': userId, 'targetPEId': peId, 'newPeParentId': newParentPEId, 'newPeName': newPeName},
success: function (data) {
var dataObj = jQuery.parseJSON(data);
console.log(dataObj);
if (dataObj.status == "success") {
alert("Permissions have been updated.");
}
//update user PEs combo
}
});
However, I am concerned of a possible race condition of the variables not getting the values in time for the ajax call.
would something like this be safer?
var userId = $("#user-permission-edit").val();
var peId = $("#user-permission-entity-list").val();
var newParentPEId = $("#new-parent-pe").val();
var newPeName = $("#pe-name-add").val();
$.when(function() {
userId = $("#user-permission-edit").val();
peId = $("#user-permission-entity-list").val();
newParentPEId = $("#new-parent-pe").val();
newPeName = $("#pe-name-add").val();
}).done(function() {
$.ajax({
type: "POST",
url: 'AddNewPE',
data: { 'targetUserId': userId, 'targetPEId': peId, 'newPeParentId': newParentPEId, 'newPeName': newPeName},
success: function (data) {
var dataObj = jQuery.parseJSON(data);
console.log(dataObj);
if (dataObj.status == "success") {
alert("Permissions have been updated.");
}
//update user PEs combo
}
});
});
Is this even necessary?
The $('....').val() method is a synchronous call - your script execution won't continue past that line until you have received the value of that element.

Assign value to global variable using $.Ajax (JQuery)

I am creating new functionality where I build a grid based on Json data returned from Ajax. I have decided I want to encapsulate this functionality within a function, so when I add/update/delete, I can on success retrieve a new representation of the data.
The problem I am having is I want to fill a global array but once my function that uses AJAX ends, I have an Array but no data. This isn't a problem when all the code is within the AJAX call but once I try to separate this in to its own function, it doesn't work as intended.
<script type="text/javascript">
var DataArray = [];
// Use this function to fill array
function retrieveNotes() {
$.ajax({
url: "http://wks52025:82/WcfDataService.svc/GetNotesFromView()?$format=json",
type: "get",
datatype: "json",
asynch:true,
success: function (data) {
returnedData = data;
$.each(data.d, function (i, item) {
DataArray[i] = [];
DataArray[i][0] = item.NotesTitle.trim();
DataArray[i][1] = item.ProfileName.trim();
DataArray[i][2] = item.IsShared;
DataArray[i][3] = item.NameOfUser.trim();
}) // End of each loop
}
});
}
$(document).ready(function () {
retrieveNotes();
DataArray;
</script>
It's asynchronous, so you'll have to wait for the ajax call to finish before you can use the data :
function retrieveNotes() {
return $.ajax({
url: "http://wks52025:82/WcfDataService.svc/GetNotesFromView()?$format=json",
type: "get",
datatype: "json"
});
}
$(document).ready(function () {
retrieveNotes().done(function(data) {
var DataArray = [];
$.each(data.d, function (i, item) {
DataArray[i] = [];
DataArray[i][0] = item.NotesTitle.trim();
DataArray[i][1] = item.ProfileName.trim();
DataArray[i][2] = item.IsShared;
DataArray[i][3] = item.NameOfUser.trim();
});
// you can only use the data inside the done() handler,
// when the call has completed and the data is returned
});
});

Categories