Cannot read property 'then' of undefined in promise - javascript

I have the above error on this method:
function addContentType(listItem){
var promise = getContentTypeOfCurrentItem(listItem.ID.toString());
promise.then(function(cname){
listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
});
return promise;
}
Entire code is here:
function GetRelatedBillingDocumentsFromList(selectProperties, currentBillCyclePath, clientCode, jobCodes, engagementCode, enhanceFunctions) {
$log.info("Retrieving related billing documents for bill cycle with name [" + currentBillCyclePath + "]");
var deferred = $q.defer();
var webUrl = _spPageContextInfo.webAbsoluteUrl;
var viewFields = spService.ConvertSelectPropertiesToViewFields(selectProperties);
// query must return the documents for the same client but in other bill cycles not the current one
var camlQuery = '<View Scope="RecursiveAll">' + viewFields +
'<Query>' +
'<Where>' +
'<And>' +
'<Eq>' +
'<FieldRef Name="ClientCode" />' +
'<Value Type="Text">'+ clientCode + '</Value>' +
'</Eq>' +
'<Neq>' +
'<FieldRef Name="ContentType" />' +
'<Value Type="Computed">Bill Cycle</Value>' +
'</Neq>' +
'</And>' +
'</Where>' +
'</Query>' +
'</View>';
var billCyclesListId = "{c23bbae4-34f7-494c-8f67-acece3ba60da}";
spService.GetListItems(billCyclesListId, camlQuery, selectProperties)
.then(function(listItems) {
var listItemsWithValues = [];
if(listItems) {
var enumerator = listItems.getEnumerator();
var promises = [];
while (enumerator.moveNext()) {
var listItem = enumerator.get_current();
var listItemValues = [];
selectProperties
.forEach(function(propertyName) {
var value = listItem.get_item(propertyName);
if(propertyName === "PwC_JobCodesMulti"){
jobvalue = "";
value.forEach(function(jobvalues){
jobvalue+= jobvalues.get_lookupValue() +";";
})
listItemValues[propertyName] = jobvalue;
}else{
listItemValues[propertyName] = value;
}
});
listItemsWithValues.push(listItemValues);
}
var promises = listItemsWithValues.map(addContentType);
Promise.all(promises).then(youCanUseTheData);
function youCanUseTheData(){
/*
At this point, each listItem holds the 'Document Type' info
*/
listItemsWithValues.forEach(function(listItem) {
var fileDirRef = listItem["FileRef"];
var id = listItem["ID"];
var title = listItem["Title"];
var serverUrl = _spPageContextInfo.webAbsoluteUrl.replace(_spPageContextInfo.webServerRelativeUrl,"");
var dispFormUrl = serverUrl + "/sites/billing/_layouts/15/DocSetHome.aspx?id="+fileDirRef;
//listItem["FileRef"] = dispFormUrl;
//listItem["Bill Cycle"] = dispFormUrl;
var parentLink = listItem["FileRef"];
arrayofstrings = parentLink.split("/");
var billCycleFolderName = arrayofstrings[arrayofstrings.length-2];
arrayofstrings.pop();
var hyperLink = '' + billCycleFolderName + '';
listItem["Bill Cycle"] = hyperLink;
});
}
}
var enhancedListItemValues = spService.SpSearchQuery.EnhanceSearchResults(listItemsWithValues, enhanceFunctions);
deferred.resolve(listItemsWithValues);
})
.catch (function (message) {
deferred.reject();
});
return deferred.promise;
}
function addContentType(listItem){
var promise = getContentTypeOfCurrentItem(listItem.ID.toString());
promise.then(function(cname){
listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
});
return promise;
}
function getContentTypeOfCurrentItem(id) {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle("Bill Cycles");
listItem = oList.getItemById(id);
clientContext.load(listItem);
listContentTypes = oList.get_contentTypes();
clientContext.load(listContentTypes);
clientContext.executeQueryAsync(
function() {
$log.info("Successfully retrieved getContentTypeOfCurrentItemt");
var ctid = listItem.get_item("ContentTypeId").toString();
var ct_enumerator = listContentTypes.getEnumerator();
while (ct_enumerator.moveNext()) {
var ct = ct_enumerator.get_current();
if (ct.get_id().toString() == ctid) {
var contentTypeName = ct.get_name();
}
}
return Promise.resolve(contentTypeName);
},
function(error, errorInfo) {
$log.warn("Retrieving getContentTypeOfCurrentItem failed");
deferred.reject(errorInfo);
}
);
}
Not sure exactly what I am missing
Update 1:
I changed the code as Niels replied tere, but then I get the error below:
Uncaught Error: The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
If I analyze the changes done, the only thing that changed on the method is the return new promise, the rest is the same and it was working before. I didnt make all changes as Niels did, just need to make this work without too much effort. :)
function GetRelatedBillingDocumentsFromList(selectProperties, currentBillCyclePath, clientCode, jobCodes, engagementCode, enhanceFunctions) {
$log.info("Retrieving related billing documents for bill cycle with name [" + currentBillCyclePath + "]");
var deferred = $q.defer();
var webUrl = _spPageContextInfo.webAbsoluteUrl;
var viewFields = spService.ConvertSelectPropertiesToViewFields(selectProperties);
// query must return the documents for the same client but in other bill cycles not the current one
var camlQuery = '<View Scope="RecursiveAll">' + viewFields +
'<Query>' +
'<Where>' +
'<And>' +
'<Eq>' +
'<FieldRef Name="ClientCode" />' +
'<Value Type="Text">'+ clientCode + '</Value>' +
'</Eq>' +
'<Neq>' +
'<FieldRef Name="ContentType" />' +
'<Value Type="Computed">Bill Cycle</Value>' +
'</Neq>' +
'</And>' +
'</Where>' +
'</Query>' +
'</View>';
var billCyclesListId = "{c23bbae4-34f7-494c-8f67-acece3ba60da}";
spService.GetListItems(billCyclesListId, camlQuery, selectProperties)
.then(function(listItems) {
var listItemsWithValues = [];
if(listItems) {
var enumerator = listItems.getEnumerator();
var promises = [];
while (enumerator.moveNext()) {
var listItem = enumerator.get_current();
var listItemValues = [];
selectProperties
.forEach(function(propertyName) {
var value = listItem.get_item(propertyName);
if(propertyName === "PwC_JobCodesMulti"){
jobvalue = "";
value.forEach(function(jobvalues){
jobvalue+= jobvalues.get_lookupValue() +";";
})
listItemValues[propertyName] = jobvalue;
}else{
listItemValues[propertyName] = value;
}
});
listItemsWithValues.push(listItemValues);
}
var promises = listItemsWithValues.map(addContentType);
Promise.all(promises).then(youCanUseTheData);
function youCanUseTheData(){
/*
At this point, each listItem holds the 'Document Type' info
*/
listItemsWithValues.forEach(function(listItem) {
var fileDirRef = listItem["FileRef"];
var id = listItem["ID"];
var title = listItem["Title"];
var serverUrl = _spPageContextInfo.webAbsoluteUrl.replace(_spPageContextInfo.webServerRelativeUrl,"");
var dispFormUrl = serverUrl + "/sites/billing/_layouts/15/DocSetHome.aspx?id="+fileDirRef;
//listItem["FileRef"] = dispFormUrl;
//listItem["Bill Cycle"] = dispFormUrl;
var parentLink = listItem["FileRef"];
arrayofstrings = parentLink.split("/");
var billCycleFolderName = arrayofstrings[arrayofstrings.length-2];
arrayofstrings.pop();
var hyperLink = '' + billCycleFolderName + '';
listItem["Bill Cycle"] = hyperLink;
});
}
}
var enhancedListItemValues = spService.SpSearchQuery.EnhanceSearchResults(listItemsWithValues, enhanceFunctions);
deferred.resolve(listItemsWithValues);
})
.catch (function (message) {
deferred.reject();
});
return deferred.promise;
}
function addContentType(listItem){
return getContentTypeOfCurrentItem(listItem.ID.toString()).then(function(cname){
listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
});
}
function getContentTypeOfCurrentItem(id) {
return new Promise(function (resolve, reject) {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle("Bill Cycles");
listItem = oList.getItemById(id);
clientContext.load(listItem);
listContentTypes = oList.get_contentTypes();
clientContext.load(listContentTypes);
clientContext.executeQueryAsync(
function() {
$log.info("Successfully retrieved getContentTypeOfCurrentItemt");
var ctid = listItem.get_item("ContentTypeId").toString();
var ct_enumerator = listContentTypes.getEnumerator();
while (ct_enumerator.moveNext()) {
var ct = ct_enumerator.get_current();
if (ct.get_id().toString() == ctid) {
var contentTypeName = ct.get_name();
}
}
resolve(contentTypeName);
},
function(error, errorInfo) {
$log.warn("Retrieving getContentTypeOfCurrentItem failed");
reject(errorInfo);
}
);
});
}

getContentTypeOfCurrentItem should return a Promise. Assuming that clientContext.executeQueryAsync does not return a promise, since it is using handlers:
function getContentTypeOfCurrentItem(id) {
return new Promise(function (resolve, reject) {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle("Bill
Cycles");
listItem = oList.getItemById(id);
clientContext.load(listItem);
listContentTypes = oList.get_contentTypes();
clientContext.load(listContentTypes);
clientContext.executeQueryAsync(
function() {
$log.info("Successfully retrieved
getContentTypeOfCurrentItemt");
var ctid = listItem.get_item("ContentTypeId").toString();
var ct_enumerator = listContentTypes.getEnumerator();
while (ct_enumerator.moveNext()) {
var ct = ct_enumerator.get_current();
if (ct.get_id().toString() == ctid) {
var contentTypeName = ct.get_name();
}
}
resolve(contentTypeName);
},
function(error, errorInfo) {
$log.warn("Retrieving getContentTypeOfCurrentItem failed");
reject(errorInfo);
}
);
});
}
addContentType can be more easy as well:
function addContentType(listItem){
return getContentTypeOfCurrentItem(listItem.ID.toString()).then(function(cname) {
listItem['Document Type'] = cname; //we add the doc type to each listItem, not only the last one
}).catch(function(error) {
$log.warn("Server error");
});
}

The getContentTypeOfCurrentItem function doesn't return anything. Just modify it to return your promise (assuming of course that clientContext.executeQueryAsync returns a promise):
function getContentTypeOfCurrentItem(id) {
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle("Bill Cycles");
listItem = oList.getItemById(id);
clientContext.load(listItem);
listContentTypes = oList.get_contentTypes();
clientContext.load(listContentTypes);
return clientContext.executeQueryAsync(
function() {
$log.info("Successfully retrieved getContentTypeOfCurrentItemt");
var ctid = listItem.get_item("ContentTypeId").toString();
var ct_enumerator = listContentTypes.getEnumerator();
while (ct_enumerator.moveNext()) {
var ct = ct_enumerator.get_current();
if (ct.get_id().toString() == ctid) {
var contentTypeName = ct.get_name();
}
}
return Promise.resolve(contentTypeName);
},
function(error, errorInfo) {
$log.warn("Retrieving getContentTypeOfCurrentItem failed");
deferred.reject(errorInfo);
}
);
}

Related

JSOM/Javascript get content type name with all other columns

I have the following method which correctly gets list items from a sharepoint query, however the content type needs a special treatment and its not returned.
function getListItems(listId, camlQueryString, selectProperties){
var deferred = $q.defer();
var context = SP.ClientContext.get_current();
var web = context.get_web();
var list = web.get_lists().getById(listId);
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml(camlQueryString);
var listItems = list.getItems(camlQuery);
//var includesString = "Include(ID,Title,AssignedTo, WorkflowOutcome, ApproverComments, FileRef, WorkflowItemId, Created, Modified)"; // + selectProperties.join(", ") + ")";
if(selectProperties) {
var includesString = convertSelectPropertiesToIncludesString(selectProperties);
context.load(listItems, includesString);
} else {
context.load(listItems);
}
context.executeQueryAsync(
function() {
$log.info("Successfully retrieved list item result");
deferred.resolve(listItems);
},
function(error, errorInfo) {
$log.warn("Retrieving list item result failed");
deferred.reject(errorInfo);
}
);
return deferred.promise;
}
I need the content type name to be returned in the same array of listitems as another field.
I have found a few examples, but I am not sure how to integrate that code into mine because it seems a double call is needed for eachitem.
Update 1
I try to use the above method from this:
function GetRelatedBillingDocumentsFromList(selectProperties, currentBillCyclePath, clientCode, jobCodes, engagementCode, enhanceFunctions) {
$log.info("Retrieving related billing documents for bill cycle with name [" + currentBillCyclePath + "]");
var deferred = $q.defer();
var webUrl = _spPageContextInfo.webAbsoluteUrl;
var viewFields = spService.ConvertSelectPropertiesToViewFields(selectProperties);
// query must return the documents for the same client but in other bill cycles not the current one
var camlQuery = '<View>' + viewFields +
'<Query>' +
'<Where>' +
//'<And>' +
'<Eq>' +
'<FieldRef Name="ClientCode" />' +
'<Value Type="Text">'+ clientCode + '</Value>' +
'</Eq>' +
// '<Neq>' +
// '<FieldRef Name="ContentType" />' +
// '<Value Type="Computed">Bill Cycle</Value>' +
// '</Neq>' +
//'</And>' +
'</Where>' +
//'<QueryOptions>' +
// '<ViewAttributes Scope="RecursiveAll" />' +
//'</QueryOptions>' +
'</Query>' +
'</View>';
var billCyclesListId = "{c23bbae4-34f7-494c-8f67-acece3ba60da}";
spService.GetListItems(billCyclesListId, camlQuery, selectProperties)
.then(function(listItems) {
var listItemsWithValues = [];
if(listItems) {
var enumerator = listItems.getEnumerator();
while (enumerator.moveNext()) {
var listItem = enumerator.get_current();
var listItemValues = [];
selectProperties
.forEach(function(propertyName) {
if(propertyName==='ContentType'){
var value = listItem.get_item('ows_ContentType');
}else{
var value = listItem.get_item(propertyName);
}
listItemValues[propertyName] = value;
});
listItemsWithValues.push(listItemValues);
}
}
// Create the full item url
listItemsWithValues.forEach(function(listItem) {
var fileDirRef = listItem["FileRef"];
var id = listItem["ID"];
var serverUrl = _spPageContextInfo.webAbsoluteUrl.replace(_spPageContextInfo.webServerRelativeUrl,"");
var dispFormUrl = serverUrl + fileDirRef + "/DispForm.aspx?ID=" + id;
listItem["FileRef"] = dispFormUrl;
});
var enhancedListItemValues = spService.SpSearchQuery.EnhanceSearchResults(listItemsWithValues, enhanceFunctions);
deferred.resolve(listItemsWithValues);
})
.catch (function (message) {
deferred.reject();
});
return deferred.promise;
}
as you can see I need a way to return content type name in the same array of values in a simple way
You can use the ows_ContentType property to get the content type name.
So, add ows_ContentType in your includesString variable or selectProperties parameter.
After that, in your code you can use it as below:
context.executeQueryAsync(
function() {
var listItemEnumerator = listItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
console.log(oListItem.get_item('ows_ContentType'));
}
},
function(error, errorInfo) {
console.log(errorInfo);
}
);
Update - Full code
var context = SP.ClientContext.get_current();
var web = context.get_web();
var list = web.get_lists().getByTitle("Test");
var includesString = "Include(ID,Title,Created, Modified, ows_ContentType)";
var camlQuery = SP.CamlQuery.createAllItemsQuery();
var listItems = list.getItems(camlQuery);
context.load(listItems, includesString);
context.executeQueryAsync(
function() {
var listItemEnumerator = listItems.getEnumerator();
while (listItemEnumerator.moveNext()) {
var oListItem = listItemEnumerator.get_current();
console.log(oListItem.get_item('ows_ContentType'));
}
},
function(error, errorInfo) {
console.log(errorInfo);
}
);

Deferred Promises in Function does not Defer Execution of Function

I'm struggling with deferred promises. I have a very ugly string:
me, company name, SSQ ID, the company you are working for (Extraction/XTR/8North) and the tier assigned to your company in question #17.
|Y132~
|Y133~
|Y134~
|Y138~
|Y139~
|Y140~
|Y141~
|Y142~
|Y143~
that I have to replace each occurrence of a "|Y000~" with a URL link. That part of the code is working correctly. The problem is that I can't figure out how to use a promise to wait on the function (which includes deferral of multiple promises) to wait until the function finishes before moving on.
I have this in my "convertString" function:
getAllClusterLinks(indices, returnString)
returnString = $scope.returnString;
Here is the convetString function:
function convertClusterText(questions, field) {
angular.forEach(questions, function (value, key) {
if (value.vchTextBeforeQuestionCluster != null) {
var str = value.vchTextBeforeQuestionCluster;
var returnString = str.replaceAll('|B', '<b>');
returnString = returnString.replaceAll("|b", "</b>");
returnString = returnString.replaceAll("|+", "<br/>");
returnString = returnString.replaceAll("|L", "<");
returnString = returnString.replaceAll("|R", ">");
returnString = returnString.replaceAll("|T", "<table border='1'>");
returnString = returnString.replaceAll("|/T", "</table>");
returnString = returnString.replaceAll("|S", "<tr>");
returnString = returnString.replaceAll("|/S", "</tr>");
returnString = returnString.replaceAll("|C", "<td>");
returnString = returnString.replaceAll("|/C", "</td>");
returnString = returnString.replaceAll("|A", "'");
returnString = returnString.replaceAll("|Q", "&");
returnString = returnString.replaceAll("|P", ";");
returnString = returnString.replaceAll("|W", """);
returnString = returnString.replaceAll("|H", "<hr style='width: 100%;'>");
returnString = returnString.replaceAll("|U", "<span style='text-decoration:underline'>");
returnString = returnString.replaceAll("|x", "</span>");
returnString = returnString.replaceAll("|N", "<span style='color:black'>");
returnString = returnString.replaceAll("|D", "<span style='color:blue'>");
returnString = returnString.replaceAll("|E", "<span style='color:red'>");
returnString = returnString.replaceAll("|G", "<span style='color:gray'>");
if (returnString.indexOf("|Y") >= 0) {
var indices = [];
var linkCode;
indices = getIndicesOf("|Y", returnString, true);
if (indices.length > 1) {
getAllClusterLinks(indices, returnString)
.then(function () {
returnString = $scope.returnString;
})
value.vchTextBeforeQuestionCluster = returnString;
}
else {
linkCode = getLink(returnString);
contractorService.gethyperlink(linkCode)
.success(function (data) {
var vchUrl = data[0].vchUrl;
var docID = getDocumentID(vchUrl);
var vchLinkName = data[0].vchLinkName;
questions[key].document = docID;
var yay = '' + vchLinkName + '';
var yCode = "|Y" + linkCode + "~";
returnString = returnString.replaceAll(yCode, yay);
value.vchTextBeforeQuestionCluster = returnString;
})
}
}
else {
value.vchTextBeforeQuestionCluster = returnString;
}
}
});
};
I need "getAllClusterLinks" to complete before executing the next line. Here is the code for "getAllClusterLinks":
function getAllClusterLinks(indices, returnString) {
var promises = [];
var times = 0
var endIndex = 0;
angular.forEach(indices, function (value, key) {
endIndex = getEndIndicesOf("~", returnString, value);
linkCode = getMultiLinks(returnString, value, endIndex)
var promise = getClusterLinks(linkCode, returnString);
promises.push(promise);
})
return $q.all(promises);
}
function getClusterLinks(linkCode, returnString) {
var deferred = $q.defer();
$scope.returnString = returnString;
contractorService.gethyperlink(linkCode)
.success(function (data) {
var vchUrl = data[0].vchUrl;
var end = vchUrl.length;
var docID = vchUrl.substring(vchUrl.indexOf("=") + 1, end);
var vchLinkName = data[0].vchLinkName;
var yay = '' + vchLinkName + '';
var yCode = "|Y" + linkCode + "~";
$scope.returnString = $scope.returnString.replaceAll(yCode, yay);
})
return deferred.promise;
}
The above code works as expected, but I need it to finish first before setting the line returnString = $scope.returnString;.
Tried this but it doesn't work:
getAllClusterLinks(indices, returnString)
.then(function () {
returnString = $scope.returnString;
})
Any assistance is greatly appreciated!
$q.all(promises) returns a promise. You should be able to use then() .
getAllClusterLinks(indices, returnString).then(function() {
returnString = $scope.returnString;
});
[https://docs.angularjs.org/api/ng/service/$q][1]
EDIT: you should resolve your deferred object
sidenote: I believe success() is already deprecated, you should use .then too
function getClusterLinks(linkCode, returnString) {
var deferred = $q.defer();
$scope.returnString = returnString;
contractorService.gethyperlink(linkCode)
.success(function (data) {
var vchUrl = data[0].vchUrl;
var end = vchUrl.length;
var docID = vchUrl.substring(vchUrl.indexOf("=") + 1, end);
var vchLinkName = data[0].vchLinkName;
var yay = '' + vchLinkName + '';
var yCode = "|Y" + linkCode + "~";
$scope.returnString = $scope.returnString.replaceAll(yCode, yay);
deferred.resolve(); // resolve here
})
return deferred.promise;
}
Try putting the subsequent line in a then() callback:
getAllClusterLinks(indices, returnString)
.then(function() {
returnString = $scope.returnString;
});
For more info about promises within angular, see the documentation

The [object object] can't be determined and shown in console

I have a function that return something like [object object] no my value that I wanted , I do almost every thing to get the value but no hope.
When I try to show that object using toSource() I got something like that.
({state:(function (){return state;}), always:(function (){deferred.done(arguments).fail(arguments);return this;}), then:(function (){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=fns[i];deferred[tuple[1]](jQuery.isFunction(fn)?function(){var returned=fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);}else{newDefer[action+"With"](this===deferred?newDefer:this,[returned]);}}:newDefer[action]);});fns=null;}).promise();}), promise:(function (obj){return obj!=null?jQuery.extend(obj,promise):promise;}), pipe:(function (){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=fns[i];deferred[tuple[1]](jQuery.isFunction(fn)?function(){var returned=fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);}else{newDefer[action+"With"](this===deferred?newDefer:this,[returned]);}}:newDefer[action]);});fns=null;}).promise();}), done:(function (){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg);}}else if(arg&&arg.length&&type!=="string"){add(arg);}});})(arguments);if(firing){firingLength=list.length;}else if(memory){firingStart=start;fire(memory);}}
return this;}), fail:(function (){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg);}}else if(arg&&arg.length&&type!=="string"){add(arg);}});})(arguments);if(firing){firingLength=list.length;}else if(memory){firingStart=start;fire(memory);}}
return this;}), progress:(function (){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg);}}else if(arg&&arg.length&&type!=="string"){add(arg);}});})(arguments);if(firing){firingLength=list.length;}else if(memory){firingStart=start;fire(memory);}}
return this;})})
Could any one explain me? And I know my function is Asynchronous.
How could solve this problem ?
Here is my code:
module.Order = Backbone.Model.extend({
initialize: function (attributes) {
Backbone.Model.prototype.initialize.apply(this, arguments);
this.pos = attributes.pos;
this.sequence_number = this.pos.pos_session.sequence_number++;
debugger;
var odoo = []
var call = this
this.uid = this.generateUniqueId();
this.pro = this.get_the_other_main().done(
function (result) {
}).always(function (result) {
odoo.push(result)
call.set({
creationDate: new Date(),
orderLines: new module.OrderlineCollection(),
paymentLines: new module.PaymentlineCollection(),
name: _t("Order ") + this.uid,
client: null,
sales_person: null,
sales_person_name: null,
new_id: odoo[0]
})});
alert(odoo[0])//// Must be adddddedd
this.selected_orderline = undefined;
this.selected_paymentline = undefined;
this.screen_data = {}; // see ScreenSelector
this.receipt_type = 'receipt'; // 'receipt' || 'invoice'
this.temporary = attributes.temporary || false;
return this;
},
get_the_other_main: function () {
var dfd = new jQuery.Deferred();
new instance.web.Model("pos.order").call('get_the_product', []).done(
function (results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
}).always(function(results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
}).always(function(results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
});
alert('')////If i remove that it will return undefind for this.pos
return dfd
You seem to have problem of asynchronous call.
(see the comments below)
// you call get_the_other_main which return a Promise !
this.get_the_other_main().then(
function (result) {
// when the Promise resolve you set this.pro,
// what is this here ?? are you sure of the beahviour ?
// |
// V
this.pro=result//got it right <---------------------- +
// |
// |
});// |
// You set this.pro to another Promise, at this moment the previous this.pro is not set !
this.pro=this.get_the_other_main().then(
function (result) {
this.pro=result //got it right <----------------------------------------+
}); // |
// when you call alert, this.pro is a Promise not resolved !at this moment the previous this.pro is not set !
alert(this.pro.toSource()) //[object object]
// logicaly it show the code source of your deffered / Promise !
to solve your issue try like that :
module.Order = Backbone.Model.extend({
initialize: function(attributes) {
var curOrder = this;
Backbone.Model.prototype.initialize.apply(this, arguments);
this.pos = attributes.pos;
this.sequence_number = this.pos.pos_session.sequence_number++;
debugger; // ??????
this.uid = this.generateUniqueId();
var odoo = []
this.get_the_other_main().then(
function(result) {
curOrder.pro = result; //got it right
curOrder.set({
creationDate : new Date(),
orderLines : new module.OrderlineCollection(),
paymentLines : new module.PaymentlineCollection(),
name : _t("Order ") + curOrder.uid,
client : null,
sales_person : null,
sales_person_name: null,
new_id : curOrder.pro
});
curOrder.selected_orderline = undefined;
curOrder.selected_paymentline = undefined;
curOrder.screen_data = {}; // see ScreenSelector
curOrder.receipt_type = 'receipt'; // 'receipt' || 'invoice'
curOrder.temporary = attributes.temporary || false;
curOrder.trigger('orderready' , curOrder);
});
return this;
// be careful because the process above is not done again, when you return this, it will be resolved later
},
get_the_other_main: function() {
var dfd = new jQuery.Deferred();
new instance.web.Model("pos.order").call('get_the_product', []).done(
function(results) {
var result = results.toString().split(',');
var stringsl = result[1];
var thenum = stringsl.replace(/^\D+/g, '');
var sasa = parseInt(thenum, 10) + 1
var zika = ('00' + sasa).slice(-4)
var the_str = result[1].slice(0, -4).toString();
var new_seq_sasa = the_str + zika
dfd.resolve(new_seq_sasa);
});
return dfd
},

Setting variable through external method in method of object

I am using the method of a javascript object to create HTML to write that object.
Within that method I have a date (in string format as a SQL Date) which I format to dd MMM YYYY in an external method. The external method works fine returning the string I need, but when I set the variable within my object's method it is returned as undefined.
Hereby the relevant code:
function CreateReview(reviewID, visitDate) {
var reviewObject = {
iD: reviewID,
visitDate: visitDate,
CreateReviewObject : function(c) {
var reviewContainer = document.createElement('div');
reviewContainer.id = 'Review_' + this.iD;
reviewContainer.className = 'Card Review';
var headerDIV = document.createElement('div');
headerDIV.className = 'Header';
var dateTagsDIV = document.createElement('div');
dateTagsDIV.className = 'DateTags';
var datesDIV = document.createElement('div');
datesDIV.className = 'Dates';
var formattedVisitDate = getFormattedDate(this.visitDate);
console.log(formattedVisitDate);
var dateDIV = document.createElement('div');
dateDIV.className = 'Date';
dateDIV.innerHTML = formattedVisitDate;
datesDIV.appendChild(dateDIV);
dateTagsDIV.appendChild(datesDIV);
headerDIV.appendChild(dateTagsDIV);
reviewContainer.appendChild(headerDIV);
return reviewContainer;
}
};
return reviewObject;
}
function getFormattedDate(input) {
input = input.replace(/-/g,'/');
var pattern = /(.*?)\/(.*?)\/(.*?)$/;
var result = input.replace(pattern,function(match,p1,p2,p3){
p2 = parseInt(p2);
p3 = parseInt(p3);
var months = ['jan','feb','maa','apr','mei','jun','jul','aug','sep','okt','nov','dec'];
var date = (p3<10?"0"+p3:p3) + " " + months[parseInt(p2-1)] + " " + p1;
console.log(date);
return date;
});
}
The output of the console in getFormattedDate is then
12 mei 2015
While in CreateReview it is
undefined
I have tried the following way as well:
function CreateReview(reviewID, restaurant, kitchenTypes, tags, pictures, ratings, thumbPicture, visitDate, introduction, description) {
var reviewObject = {
iD: reviewID,
visitDate: visitDate,
CreateReviewObject : function(c) {
var getFormattedVisitDate = function(visitDate) {
return function() { getFormattedDate(visitDate); };
};
var reviewContainer = document.createElement('div');
reviewContainer.id = 'Review_' + this.iD;
reviewContainer.className = 'Card Review';
var headerDIV = document.createElement('div');
headerDIV.className = 'Header';
var dateTagsDIV = document.createElement('div');
dateTagsDIV.className = 'DateTags';
var datesDIV = document.createElement('div');
datesDIV.className = 'Dates';
var formattedVisitDate = getFormattedVisitDate(this.visitDate);
console.log(formattedVisitDate);
var dateDIV = document.createElement('div');
dateDIV.className = 'Date';
dateDIV.innerHTML = formattedVisitDate;
datesDIV.appendChild(dateDIV);
dateTagsDIV.appendChild(datesDIV);
headerDIV.appendChild(dateTagsDIV);
reviewContainer.appendChild(headerDIV);
return reviewContainer;
}
};
return reviewObject;
}
function getFormattedDate(input) {
input = input.replace(/-/g,'/');
var pattern = /(.*?)\/(.*?)\/(.*?)$/;
var result = input.replace(pattern,function(match,p1,p2,p3){
p2 = parseInt(p2);
p3 = parseInt(p3);
var months = ['jan','feb','maa','apr','mei','jun','jul','aug','sep','okt','nov','dec'];
var date = (p3<10?"0"+p3:p3) + " " + months[parseInt(p2-1)] + " " + p1;
console.log(date);
return date;
});
}
Which gives me this output in in CreateReview:
return function() { getFormattedDate(visitDate); };
Why does the CreateReview call return undefined when the console does not?
In your function getFormattedDate(), you have
var result = input.replace(pattern, function(match,p1,p2,p3) {... return date; });
so result contains the returned value of the replace function, but getFormattedDate doesn't return anything ==> undefined when called from CreateReview.
Add return result; at the end of the function getFormattedDate.

Creating JSON request data with javascript

I need to create data for a JSON request with the inputs taken from an html form. The data format that I want to generate is like below.
{
"applicationName":"Tesing",
"cpuCount":"12",
"hostdescName":"localhost",
"maxMemory":"0",
"maxWallTime":"0",
"minMemory":"0",
"nodeCount":"1",
"processorsPerNode":"12",
"serviceDesc":{
"inputParams":[
{
"dataType":"input",
"description":"my input",
"name":"myinput",
"type":"String"
},
{
"dataType":"input",
"description":"my input",
"name":"myinput",
"type":"String"
}
],
"outputParams":[
{
"dataType":"output",
"description":"my output",
"name":"myoutput",
"type":"String"
},
{
"dataType":"output",
"description":"my output",
"name":"myoutput",
"type":"String"
}
]
}
}
My code looks like below;
var jasonRequest = {};
jasonRequest["applicationName"] = appName;
jasonRequest["cpuCount"] = cpuCount;
jasonRequest["hostdescName"] = hostName;
jasonRequest["maxMemory"] = maxMemory;
jasonRequest["maxWallTime"] = ""; //TODO
jasonRequest["minMemory"] = ""; //TODO
jasonRequest["nodeCount"] = nodeCount;
jasonRequest["processorsPerNode"] = ""; //TODO
var inArray = new Array();
for(var j=0; j<inputCount; j++) {
var input = {};
input["dataType"] = "input";
input["description"] = "empty";
input["name"] = $("#inputName" + j+1).val();
input["type"] = $("#inputType" + j+1).val();
inArray[j] = input;
}
var outArray = new Array();
for(var j=0; j<outputCount; j++) {
var output = {};
output["dataType"] = "output";
output["description"] = "empty";
output["name"] = $("#outputName" + j+1).val();
output["type"] = $("#outputType" + j+1).val();
outArray[j] = output;
}
var serviceDesc = {};
serviceDesc["inputParams"] = inArray;
serviceDesc["outputParams"] = outArray;
jasonRequest["serviceDesc"] = serviceDesc;
alert("printing inArray");
alert(inArray.toSource().toString());
alert(JSON.stringify(jasonRequest));
The data created by this code is like below. I could use strings and create the message by concatenating it but I don't think that is a nice way of doing this. As you can see the inputParams and outputParams are not properly populated. Can you suggest how can I properly generate this message.
{
"applicationName":"Tesing",
"cpuCount":"12",
"hostdescName":"localhost",
"maxMemory":"0",
"maxWallTime":"0",
"minMemory":"0",
"nodeCount":"1",
"processorsPerNode":"12",
"serviceDesc":{"inputParams":"","outputParams":[]}}
[EDIT]
My code looks like below.
$(document).ready(function(){
var inputCount = 0;
var outputCount = 0;
$("p1").live("click", function(){
inputCount++;
$(this).after("<br/>");
$(this).after("Input Name *:" +
"<input type="text" id="inputName" + inputCount + "" name="inputName" + inputCount + "" value="echo_input" size="50"><br/>");
$(this).after("Input Type *:" +
"<input type="text" id="inputType" + inputCount + "" name="inputType" + inputCount + "" value="String" size="50"><br/>");
});
$("p2").live("click", function(){
$(this).after("Output Name *:" +
"<input type="text" id="outputName" + outputCount + "" name="outputName" + outputCount + "" value="echo_output" size="50"><br/>");
$(this).after();
$(this).after("Output Type *:" +
"<input type="text" id="outputType" + outputCount + "" name="outputType" + outputCount + "" value="String" size="50"><br/>");
});
$('[name="btn2"]').click(function(){
var appName = $("#appName1").val();
var exeuctableLocation = $("#exeuctableLocation1").val();
var scratchWorkingDirectory = $("#scratchWorkingDirectory1").val();
var hostName = $("#hostName1").val();
var projAccNumber = $("#projAccNumber1").val();
var queueName = $("#queueName1").val();
var cpuCount = $("#cpuCount1").val();
var nodeCount = $("#nodeCount1").val();
var maxMemory = $("#maxMemory1").val();
var serviceName = $("#serviceName1").val();
var inputName1 = $("#inputName1").val();
var inputType1 = $("#inputType1").val();
var outputName = $("#outputName1").val();
var outputType = $("#outputType1").val();
var jsonRequest = {};
jsonRequest["applicationName"] = appName;
jsonRequest["cpuCount"] = cpuCount;
jsonRequest["hostdescName"] = hostName;
jsonRequest["maxMemory"] = maxMemory;
jsonRequest["maxWallTime"] = ""; //TODO
jsonRequest["minMemory"] = ""; //TODO
jsonRequest["nodeCount"] = nodeCount;
jsonRequest["processorsPerNode"] = ""; //TODO
var inArray = [];
for(var j=0; j<inputCount; j++) {
var input = {};
input["dataType"] = "input";
input["description"] = "empty";
input["name"] = $("#inputName" + j+1).val();
input["type"] = $("#inputType" + j+1).val();
inArray[j] = input;
}
var outArray = new Array();
for(var j=0; j<outputCount; j++) {
var output = {};
output["dataType"] = "output";
output["description"] = "empty";
output["name"] = $("#outputName" + j+1).val();
output["type"] = $("#outputType" + j+1).val();
outArray[j] = output;
}
var serviceDesc = {};
serviceDesc["inputParams"] = inArray;
serviceDesc["outputParams"] = outArray;
jsonRequest["serviceDesc"] = serviceDesc;
alert("printing inArray");
alert(inArray.toSource().toString());
alert(JSON.stringify(jsonRequest));
$.ajax({
beforeSend: function(x) {
if (x && x.overrideMimeType) {
x.overrideMimeType("application/j-son;charset=UTF-8");
}
},
type: "POST",
dataType: "json",
contentType: "application/json;charset=utf-8",
url: "http://localhost:7080/airavata-registry-rest-services/registry/api/applicationdescriptor/build/save/test",
data: jasonRequest
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});
});
});
</script>
What's inputCount and outputCount? Seems like they are zero or NaN or something, so you get empty arrays. Yet, your code will still print "inputParams":[] instead of "inputParams":"".
To get a nice output (not that it would be needed for your app, only for debugging), you can use the third parameter of JSON.stringify.

Categories