CRM 2011: Getting entity with Javascript - json

I am working on some CRM 2011 Online customisations and I need to get an entity using javascript.
The entity I need will be based on the ID value of another field (a Contact entity) - this Contact ID I can get fine.
The entity I want is a custom entity. There may be multiple matches based on the Contact ID so I just want to get the first one in the list (order not important)
So far I have looked into a few ways to do this...
OData - I couldn't find enough examples on this as to what query expressions I can create, also I don't know if/how to make this work for custom entities
FetchXML - I can create a nice FetchXML query using the built-in "advanced find" too and would be happy to call this from javascript if anyone can help? I found one promising answer here but I could not see how the "results" return data was being set (Service.Fetch function)
SOAP Request - First thing I tried is a similar method as I could have done in CRM 4 but this does not seem to work. Although the request executes, my result data just seems to be empty. This is all I have code for so if any one can spot a problem with the code below then that would be great.
EDIT: I have spotted some redundant query data (I had removed link opening tags but left closing tags) - since removing this I now get XML result data... however, the where clause does not seem to apply (just get list of all entities)
var xml = "<?xml version='1.0' encoding='utf-8'?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
"<soap:Body>" +
"<RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
"<query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
"<q1:EntityName>new_vehicle</q1:EntityName>" +
"<q1:ColumnSet xsi:type='q1:ColumnSet'>" +
"<q1:Attributes>" +
"<q1:Attribute>new_vehicleid</q1:Attribute>" +
"<q1:Attribute>new_primarydriver</q1:Attribute>" +
"<q1:Attribute>statuscode</q1:Attribute>" +
"<q1:Attribute>new_registration</q1:Attribute>" +
"</q1:Attributes>" +
"</q1:ColumnSet>" +
"<q1:Distinct>false</q1:Distinct>" +
"<q1:Conditions>" +
"<q1:Condition>" +
"<q1:AttributeName>new_primarydriver</q1:AttributeName>" +
"<q1:Operator>Equal</q1:Operator>" +
"<q1:Values>" +
"<q1:Value xmlns:q2='http://microsoft.com/wsdl/types/' xsi:type='q2:guid'>" +
customerID +
"</q1:Value></q1:Values></q1:Condition>" +
"</q1:Conditions>" +
"</query></RetrieveMultiple>" +
"</soap:Body></soap:Envelope>";
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
var result = xmlHttpRequest.responseXML.xml;
var doc = new ActiveXObject("MSXML2.DOMDocument");
doc.async = false;
doc.loadXML(result);
var id = doc.selectSingleNode("//new_vehicleid");
var registration = doc.selectSingleNode("//new_registration");
if(id == null)
return null;
var vehicle = new Array();
value[0] = new Object();
value[0].id = id;
value[0].name = registration;
value[0].entityType = "new_vehicle";
return vehicle;
Sorry about the big code post but hopefully somebody who has a better understanding can help

Firstly, thanks to GlennFerrieLive for his answer post. The samples I found with the Dynamics CRM 2011 SDK (well just one in particular) really helped and the JSON parser included was perfect for the job!
I am posting this answer to give a full example of how I did it with some important comments to pay attention to which may not be so obvious from the SDK examples.
Get selected ID value from lookup field
The aim of my task was to use javascript to get set a lookup field, based on the selected data of another lookup entity. The entity to set is "new_vehicle" and the entity to query on is "customer".
First job is to get the ID value of the contact lookup field...
var customerItem = Xrm.Page.getAttribute("customerid").getValue();
var customerID = customerItem[0].id;
Querying an entity using an ID
Next is the part where I used the customerID value to find the vehicle that is currently assigned to them (the entity I want to use to set a lookup field).
First problem I found was that when querying with OData, the ID value does not seem to work with curly brackets {} - so these need to be removed...
customerID = customerID.replace('{', '').replace('}', '');
Next we get the oDataPath...
var oDataPath = Xrm.Page.context.getServerUrl() + "/xrmservices/2011/organizationdata.svc";
Then we can construct the OData query...
var filter = "/new_vehicleSet?" +
"$select=new_vehicleId,new_Registration" +
"&$filter=new_PrimaryDriver/Id eq (guid'" + customerID + "')" +
"&$orderby=new_LastAllocationDate desc" +
"&$top=1";
NOTE: There are a couple of important things to note here...
When using a guid value you must explicitly say it is a guid using (guid'xxx')
When filtering by a lookup entity (e.g. new_PrimaryDriver) you must append the value to query (e.g. Id) - this results in new_PrimaryDriver/Id
Once we have the query setup we can request the data as follows...
var retrieveRecordsReq = new XMLHttpRequest();
retrieveRecordsReq.open("GET", oDataPath + filter, true);
retrieveRecordsReq.setRequestHeader("Accept", "application/json");
retrieveRecordsReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveRecordsReq.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
var retrievedRecords = JSON.parse(retrieveRecordsReq.responseText).d;
if(retrievedRecords.results.length > 0)
{
var vehicle = retrievedRecords.results[0];
SetLookup("new_replacedvehicle", vehicle.new_vehicleId, vehicle.new_Registration, "new_vehicle");
}
}
}
};
retrieveRecordsReq.send();
Note that this is an asynchronous call and the onreadystatechange function will be processed upon completion, in this function we do a couple of checks to see if it was a success and the we parse the resulting JSON data - the JSON.Parse function has been included at the bottom of this post (but is available from the SDK)
Setting a lookup field using the entity queried above
The other function to make note of here is SetLookup which is just a simple helper function I added to set a lookup field. This is as follows...
function SetLookup(fieldName, idValue, textValue, typeValue)
{
var value = new Array();
value[0] = new Object();
value[0].id = idValue;
value[0].name = textValue;
value[0].typename = typeValue;
Xrm.Page.getAttribute(fieldName).setValue(value);
}
JSON parse function
This is the JSON helper function that was used in the above code (JSON.parse), pasted as it was found in the SDK...
if (!this.JSON) { this.JSON = {}; } (function () { function f(n) { return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function (key) { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) { return this.valueOf(); }; } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' }, rep; function quote(string) { escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { var i, k, v, length, mind = gap, partial, value = holder[key]; if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } if (typeof rep === 'function') { value = rep.call(holder, key, value); } switch (typeof value) { case 'string': return quote(value); case 'number': return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': return String(value); case 'object': if (!value) { return 'null'; } gap += indent; partial = []; if (Object.prototype.toString.apply(value) === '[object Array]') { length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } if (typeof JSON.stringify !== 'function') { JSON.stringify = function (value, replacer, space) { var i; gap = ''; indent = ''; if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } } else if (typeof space === 'string') { indent = space; } rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } return str('', { '': value }); }; } if (typeof JSON.parse !== 'function') { JSON.parse = function (text, reviver) { var j; function walk(holder, key) { var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '#').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { j = eval('(' + text + ')'); return typeof reviver === 'function' ? walk({ '': j }, '') : j; } throw new SyntaxError('JSON.parse'); }; } } ());

Related

How to prevent my github page from making post title 'title-cased'

I have created a github page and have chosen one of proposed Jekyll themes called minima. To add a post I have created a file called 2018-11-16-My-first-post-on-github.md. However, the post title displayed is a text converted to title case: My First Post On Github, so every first letter in each word is made upper case. How can I prevent that? Is this theme-dependent?
exports.toTitleCase = function(str){
var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
return (str+'').replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function(match, index, title){
if (index > 0 && index + match.length !== title.length &&
match.search(smallWords) > -1 && title.charAt(index - 2) !== ":" &&
(title.charAt(index + match.length) !== '-' || title.charAt(index - 1) === '-') &&
title.charAt(index - 1).search(/[^\s-]/) < 0) {
return match.toLowerCase();
}
if (match === 'tus') {
return match;
}
if (match.substr(1).search(/[A-Z]|\../) > -1) {
return match;
}
// Avoid uppercasing 'mod_deflate', apt-file - kvz
if (match.match(/.[\_\-\/\d]./)) {
return match;
}
// Avoid uppercasing '`frame`', '/sftp/import' - kvz
if (match.match(/(^[`\/]|[`]$)/)) {
return match;
}
// Avoid uppercasing: 'tmpfs' or anything that doesn't have a vowel - kvz
if (!match.match(/[aeiou]/)) {
return match;
}
return match.charAt(0).toUpperCase() + match.substr(1);
});
};
exports.newPost = function (content, opts, cb){
var self = this;
var matches = [];
var oldTitle = '';
var newTitle = '';
var oldLine = '';
var heading = '';
var newLine = '';
var changes = [];
var words = [];
var frontMatter = content.split('---')[1];
if (frontMatter) {
matches = frontMatter.match(/^(title\s*:\s*)\"?(.+?)\"?[\ \t]*$/im);
oldTitle = matches[2];
newTitle = self.toTitleCase(oldTitle).trim();
oldLine = matches[0];
newLine = matches[1] + '"' + newTitle + '"';
if (oldLine !== newLine) {
changes.push({oldTitle: oldTitle, newTitle: newTitle});
content = content.replace(oldLine, newLine);
}
}
if (opts.body === true) {
matches = content.match(/^\#{1,6} ([a-zA-Z0-9\-\;\!\?\%\&\;\:\.\/\(\)\ ]+)$/mg)
for (var i in matches) {
words = matches[i].split(' ')
heading = words.shift();
oldTitle = words.join(' ');
newTitle = self.toTitleCase(oldTitle).trim();
oldLine = heading + ' ' + oldTitle;
newLine = heading + ' ' + newTitle;
if (oldLine !== newLine) {
changes.push({oldTitle: oldTitle, newTitle: newTitle});
content = content.replace(oldLine, newLine);
}
}
}
if (changes.length === 0) {
content = null;
}
return cb(null, content, changes);
};
Jekyll automatically converts your post title to uppercase upon import. You can fix this by using a plugin, or by using a YAML file or Front matter to specify your title value directly.

Convert a JSON object to a particular CSV format

I want to convert this
{
"Name A":{
"Name B":{
"Name C":"Value C",
"Name D":"Value D",
"Name E":"Value E"
}
}
}
to this
Name A,,,
,Name B,,
,, Name C,Value C
,, Name D,Value D
,,Name E,Value E
It will look like this when opened in excel
I'm attempting to achieve this by running a small script, but before that I wanted to check if there is any node package or tool that can achieve this easily. Any clues?
Might be you can try with this npm module csvjson.
The link is here:- https://www.npmjs.com/package/csvjson
I solved this by writing my own script. I had to tweak a little to fit my necessity according to the format of the data. It is not the most elegant solution. It was quick dirty solution I got working. Still it's a good reference if anyone wants to try writing their own script to convert JSON to CSV
var fs = require('fs');
var file = 'templateEn.json';
var content = fs.readFileSync(file, { encoding: 'binary' });
var obj = JSON.parse(content);
var jsonString = ""
var lineEnd = "\r\n";
var firstLevelKeys = Object.keys(obj);
jsonString += firstLevelKeys[0] + ",,,,," + lineEnd;
var secondLevelKeys = Object.keys(obj["en"]);
secondLevelKeys.forEach(key => {
jsonString += ',' + key +',,,,'+ lineEnd
var thirdLevelKeys = Object.keys(obj["en"][key]);
thirdLevelKeys.forEach(key2=>{
if (typeof obj["en"][key][key2] === "string"){
jsonString += ",," + key2 + ',"' + obj["en"][key][key2]+'",,'+ lineEnd;
}
else if (typeof obj["en"][key][key2] === "object"){
var fourthLevelKeys = Object.keys(obj["en"][key][key2]);
jsonString += ',,' + key2 + ',,,' + lineEnd
fourthLevelKeys.forEach(key3 => {
if (typeof obj["en"][key][key2][key3] === "string") {
jsonString += ",,," + key3 + ',"' + obj["en"][key][key2][key3] + '",' + lineEnd;
}
else if (typeof obj["en"][key][key2][key3] === "object") {
var fifthLevelKeys = Object.keys(obj["en"][key][key2][key3]);
jsonString += ',,,' + key3 + ',,' + lineEnd
fifthLevelKeys.forEach(key4 => {
if (typeof obj["en"][key][key2][key3][key4] === "string") {
jsonString += ",,,," + key4 + ',"' + obj["en"][key][key2][key3][key4] + '"' + lineEnd;
}
})
}
})
}
});
});
fs.writeFileSync("generated.csv", jsonString, "utf8");

Generate Random Mathematical Functions

This is kind of a weird question, and might not be entirely appropriate for Stack Overflow, but I couldn't find anything about it online, so here it is...
Is there a way (or what is the best way) to generate random mathematical functions? By this I don't mean that I want a function that generates a random number (line an RNG), but rather I want to dynamically create some function which which maps one or more real inputs from a domain to a single output using some mutate-able rules.
For example, in the simplest case, I could just generate a function of the form f(x1,x2) -> Y by applying a random operator to x1 and x2. For example f could be:
f = x1 + x2
or f = x1 - x2
or f = x1 * x2
etc...
However, I would like to be able to include more complex formulas including trigonometry, power functions, pseudorandom constants, possibly some calculus functions, etc... Obviously, I cant just concatenate different chunks in a completely random way, since these functions always need to always have valid syntax.
This isn't for anything crypto-related so it doesnt have to be perfect, but the more entropy the better. It would also be great if there is an easy way to keep track of what operations are being preformed and mutate them.
I'm not sure if anyone has any insights on this, or if it even made sense, but thank you anyway
I would suggest that you try to generate random expression trees; pseudocode (somewhat Scala-inspired) for that might look something like this:
NVars = 2
def generateTree(level) = {
if (level > 100) { generateVarref() }
else {
val choice = randomChoice(4)
switch (choice) {
case 0 => generateVarref()
case 1 => generateConstant()
case 2 => generateUnary(level + 1)
case 3 => generateBinary(level + 1)
}
}
}
def generateVarref() = {
val c = randomChoice(NVars)
VarRef(c)
}
def generateConstant() = {
Number(randomChoice(100))
}
def generateUnary(level) = {
val c = randomChoice(6)
val subexpr = generateTree(level)
switch (c) {
case 0 => Negate(subexpr)
case 1 => Sin(subexpr)
// etc. More unary functions here
}
}
def generateBinary(level) = {
val c = randomChoice(4)
val sub1 = generateTree(level)
val sub2 = generateTree(level)
switch (c) {
case 0 => Plus(sub1, sub2)
case 1 => Minus(sub1, sub2)
case 2 => Times(sub1, sub2)
case 3 => Divide(sub1, sub2)
}
}
Where Plus, Varref, etc are constructors for an expression type that implements a method that will then allow you to evaluate the expression at given values.
Let's assume your functions have 2 variables x1 and x2 (if this assumption is too restrictive just adapt my answer to n variables x1, ..., xn.)
[Start] Generate random polynomial functions
This would entail
modeling polynomials in 2 variables (x1 and x2)
implementing the evaluation of polynomials on (any) particular values of the variables
generating random polynomial functions by taking a random degree (up to a certain max) and random coefficients (inside a given interval)
[Compose] Enable Function Composition
This would entail
implementing the composition of functions so that if, say f, g and h are functions in your model (randomly generated or not), then f(g,h) is also a function in your model.
[Enrich] Add new function families to your model
Here you have to consider (and implement) other types of functions to the one you already have (polynomial): rational, trigonometric, logarithmic, exponential, etc. For every new type, you will have to model them and also, to implement a way of generating random instances of them (much as you did for the polynomials.)
[Generate] Create random functions combining all of the above
Choose some types randomly
For every type, generate a random instance
Compose all the types into a final result.
[Iterate] Go to [Enrich] and add new types of functions
Ditto.
Thanks everyone for the help. What I ended up doing was something along the lines of a parse tree, recursively generating new nodes with 2, 1, or 0 children (for binary or unary operators or constants). You could cap depth by checking Node.getDepth(). Below is some JavaScript code showing this process. I'm not sure how useful it will be but it works pretty much how I had envisioned.
'use strict';
var print = console.log;
function randint(a, b) {
return Math.floor((Math.random() * (b + 1 - a)) + a);
}
function Node(parentNode, numberOfVars,
mode, weight, method, numberOfChildren, varIndex, value) {
this.mode = mode ? mode : randint(0, 3);
this.parent = parentNode;
this.weight = weight ? weight : 1;
if (this.mode == 0) { //constant
this.value = value ? value : 1;
} else if (this.mode == 1) { //variable
this.varIndex = varIndex ? varIndex : randint(0, numberOfVars - 1);
} else if (this.mode == 2) { //binary
this.method = method ? method : Node.binary[randint(0, Node.binary.length - 1)];
} else if (this.mode == 3) { //unary
this.method = method ? method : Node.unary[randint(0, Node.unary.length - 1)];
}
if (numberOfChildren) {
this.children = new Array(numberOfChildren);
} else {
this.children = [];
if (this.mode == 2) { //binary
this.children = [new Node(this, numberOfVars),
new Node(this, numberOfVars)
];
} else if (this.mode == 3) { //unary
this.children = [new Node(this, numberOfVars)];
}
}
//Methods
this.execute = function(top_level_variables) {
print("executing " + this.mode);
var inputs = [];
this.children.forEach(function(child, index) {
print("child index " + index);
inputs.push(child.execute(top_level_variables) * child.weight);
});
print(" inputs = " + inputs);
if (this.mode == 0) {
print(" mode == 0");
return this.constant();
}
if (this.mode == 1) {
print(" mode == 1");
return this.variable(top_level_variables);
}
if (this.mode == 2) {
print(" mode == 2");
return this.method(inputs[0], inputs[1]);
}
if (this.mode == 3) {
print(" mode == 3");
return this.method(inputs[0]);
}
};
var getIndent = function(indent) {
var str = "";
if (indent === 0)
return str;
for (var i = 0; i < indent; i++) {
str += " | ";
}
return str;
};
this.getTree = function(indent) {
if (this.mode == 0) {
print(getIndent(indent) + "(" + this.value + ")");
} else if (this.mode == 1) {
print(getIndent(indent) + "x[" + this.varIndex + "]");
} else if (this.mode == 2) {
print(getIndent(indent) + this.method.name);
this.children[0].getTree(indent + 1);
this.children[1].getTree(indent + 1);
} else if (this.mode == 3) {
print(getIndent(indent) + this.method.name);
this.children[0].getTree(indent + 1);
}
};
this.getStr = function() {
if (this.mode == 0) {
return this.value;
} else if (this.mode == 1) {
return "x[" + this.varIndex + "]";
} else if (this.mode == 2) {
return this.method.name + "( " + this.children[0].getStr() + ", " + this.children[1].getStr() + " )";
} else if (this.mode == 3) {
return this.method.name + "( " + this.children[0].getStr() + " )";
}
};
}
Node.binary = [
function add(a, b) {
return a + b
},
function multiply(a, b) {
return a * b
},
function power(a, b) {
return Math.pow(a, b)
}
];
Node.unary = [
function sin(a) {
return Math.sin(a)
}
];
Node.prototype.constant = function() {
return this.value
};
Node.prototype.variable = function(variables) {
return variables[this.varIndex]
};
//Test
var a = new Node(null, 2, 2);
a.getTree(0);
print(a.getStr())
print(a.getDepth());
var b = a.execute([1, 3]);
print(b);

Funky IE JSON conversions

When running our AngularJS app in IE11 everything looks great in the debugger, but when our app encodes the data as JSON to save to our database, we get bad results.
Our app obtains a record from our database, then some manipulation is done and then the data is saved back to the server from another model.
Here is the data I got back from the server in the setAttendanceGetSInfo() function below:
{"data":{"Start":"2014-10-16T19:36:00Z","End":"2014-10-16T19:37:00Z"},
This is the code used to "convert the data" to 3 properties in our model:
var setAttendanceGetSInfo = function (CourseId, PID) {
return setAttendanceInfo(CourseId, PID)
.then(function (result) {
return $q.all([
$http.get("../api/Axtra/getSInfo/" + model.event.Id),
$http.get("../api/Axtra/GetStartAndEndDateTime/" + aRow.Rid)
]);
}).then(function (result) {
var r = result.data;
var e = Date.fromISO(r.Start);
var f = Date.fromISO(r.End);
angular.extend(model.event, {
examDate: new Date(e).toLocaleDateString(),
examStartTime: (new Date(e)).toLocaleTimeString(),
examEndTime: (new Date(f)).toLocaleTimeString()
});
return result.sInfo;
});
};
fromISO is defined as:
(function(){
var D= new Date('2011-06-02T09:34:29+02:00');
if(!D || +D!== 1307000069000){
Date.fromISO= function(s){
var day, tz,
rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
p= rx.exec(s) || [];
if(p[1]){
day= p[1].split(/\D/);
for(var i= 0, L= day.length; i<L; i++){
day[i]= parseInt(day[i], 10) || 0;
};
day[1]-= 1;
day= new Date(Date.UTC.apply(Date, day));
if(!day.getDate()) return NaN;
if(p[5]){
tz= (parseInt(p[5], 10)*60);
if(p[6]) tz+= parseInt(p[6], 10);
if(p[4]== '+') tz*= -1;
if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
}
return day;
}
return NaN;
}
}
else{
Date.fromISO= function(s){
return new Date(s);
}
}
})()
Take a look at the screenshot of the event model data:
But, if I eval the event model using JSON.stringify(model.event), I get this:
{\"examDate\":\"?10?/?16?/?2014\",\"examStartTime\":\"?2?:?44?:?00? ?PM\",\"examEndTime\":\"?2?:?44?:?00? ?PM\"}
And this is the JSON encoded data that actually got stored on the DB:
"examDate":"¿10¿/¿16¿/¿2014","examStartTime":"¿2¿:¿36¿:¿00¿ ¿PM","examEndTime":"¿2¿:¿37¿:¿00¿ ¿PM"
What is wrong here and how can I fix this? It works exactly as designed in Chrome and Firefox. I have not yet tested on Safari or earlier versions of IE.
The toJSON for the date class isn't defined perfectly the same for all browsers.
(You can see a related question here: Discrepancy in JSON.stringify of date values in different browsers
I would suspect that you have a custom toJSON added to the Date prototype since your date string doesn't match the standard and that is likely where your issue is. Alternatively, you can use the Date toJSON recommended in the above post to solve your issues.
First, I modified the fromISO prototype to this:
(function () {
var D = new Date('2011-06-02T09:34:29+02:00');
if (!D || +D !== 1307000069000) {
Date.fromISO = function (s) {
var D, M = [], hm, min = 0, d2,
Rx = /([\d:]+)(\.\d+)?(Z|(([+\-])(\d\d):(\d\d))?)?$/;
D = s.substring(0, 10).split('-');
if (s.length > 11) {
M = s.substring(11).match(Rx) || [];
if (M[1]) D = D.concat(M[1].split(':'));
if (M[2]) D.push(Math.round(M[2] * 1000));// msec
}
for (var i = 0, L = D.length; i < L; i++) {
D[i] = parseInt(D[i], 10);
}
D[1] -= 1;
while (D.length < 6) D.push(0);
if (M[4]) {
min = parseInt(M[6]) * 60 + parseInt(M[7], 10);// timezone not UTC
if (M[5] == '+') min *= -1;
}
try {
d2 = Date.fromUTCArray(D);
if (min) d2.setUTCMinutes(d2.getUTCMinutes() + min);
}
catch (er) {
// bad input
}
return d2;
}
}
else {
Date.fromISO = function (s) {
return new Date(s);
}
}
Date.fromUTCArray = function (A) {
var D = new Date;
while (A.length < 7) A.push(0);
var T = A.splice(3, A.length);
D.setUTCFullYear.apply(D, A);
D.setUTCHours.apply(D, T);
return D;
}
Date.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
})()
Then I added moment.js and formatted the dates when they get stored:
var SaveAffRow = function () {
// make sure dates on coursedate and event are correct.
var cd = model.a.courseDate;
var ed = model.event.examDate;
var est = model.event.examStartTime;
var eet = model.event.examEndTime;
model.a.courseDate = moment(cd).format("MM/DD/YYYY");
model.event.examDate = moment(ed).format("MM/DD/YYYY");
model.event.examStartTime = moment(est).format("MM/DD/YYYY hh:mm A");
model.event.examEndTime = moment(eet).format("MM/DD/YYYY hh:mm A");
affRow.DocumentsJson = angular.toJson({a: model.a, event: model.event});
var aff = {};
if (affRow.Id != 0)
aff = affRow.$update({ Id: affRow.Id });
else
aff = affRow.$save({ Id: affRow.Id });
return aff;
};
and when they get read (just in case they are messed up already):
var setAttendanceGetSInfo = function (CourseId, PID) {
return setAttendanceInfo(CourseId, PID)
.then(function (result) {
return $q.all([
$http.get("../api/Axtra/getSInfo/" + model.event.Id),
$http.get("../api/Axtra/GetStartAndEndDateTime/" + aRow.Rid)
]);
}).then(function (result) {
var r = result.data;
var e = Date.fromISO(r.Start);
var f = Date.fromISO(r.End);
angular.extend(model.event, {
examDate: moment(e).format("MM/DD/YYYY"),
examStartTime: moment(e).format("MM/DD/YYYY hh:mm A"),
examEndTime: moment(f).format("MM/DD/YYYY hh:mm A")
});
return result.sInfo;
});
};

json not matching model

In EXTJS i will use a model and store for my grid. Now is the problem that sometimes the json will not match the model. There will be less information then in my model. When this happens EXTJS will not show any data in the grid. So i looked for a fix and found this:
Ext.define('App.Reader', {
extend: 'Ext.data.reader.Json',
extractData: function(root) {
var me = this,
values = [],
records = [],
Model = me.model,
i = 0,
length = root.length,
idProp = me.getIdProperty(),
node, id, record;
if (!root.length && Ext.isObject(root)) {
root = [root];
length = 1;
}
for (; i < length; i++) {
node = root[i];
values = me.extractValues(node);
id = me.getId(node);
record = new Model(values, id, node);
records.push(record);
if (me.implicitIncludes) {
me.readAssociated(record, node);
}
}
return records;
},
extractValues: function(data) {
var fields = this.getFields(),
i = 0,
length = fields.length,
output = {},
field, value;
for (; i < length; i++) {
field = fields[i];
value = this.extractorFunctions[i](data);
if(value === undefined)
{
Ext.iterate(fields, function(key, val) {
if (data[key] === undefined & i==val) {
console.log( "Model field <" + key.name + "> does not exist in data/node.");
value = "INVALID OR MISSING FIELD NAME";
var p = 0;
for(var prop in data) {
if(p==i){
if(data.hasOwnProperty(prop))console.log("Instead of <" + key.name + "> we have <" + prop + "> with value <" + data[prop]+ ">");
}
p++;
}
}
}, this);
}
output[field.name] = value;
}
return output;
}
});
var myReader = new App.Reader({
type:'json'
});
i found this online. But when i use this with EXTJS 4.1.1 there is an error in ext-all: TypeError: j is undefined.
Where should i look for the fix for this?
There's no need to do something complicated to solve this trivial problem. Read up on Ext.data.Model and Ext.data.Field, configure your Model properly and you're all set.