EXT Js Complex JSON Response Handling : Grid Insertion - json

Hello I am trying to insert a JSON record into the grid dynamically.
My server response is as below :
{
"studentDetails":{
"status":"ACTIVE",
"subject":"MATH",
"paymentOptions":"EFT",
"idStudent":71,
"firstName":"Alli",
"lastName":"Alli",
"middleName":"Alli",
"grade":"A",
"kumonLevel":"FK",
"parentId":68,
"userId":1,
"parentBean":{
"parentFirstName":"Alli",
"idParent":68,
"parentMiddleName":"Alli",
"parentLastName":"Alli",
"parentEmailId":"haigopi#gmail.com",
"parentPhoneNumber":"3173797945"},
"startTimeSlot":"12:00 AM",
"endTimeSlot":"12:15 AM",
"dob":"2012-07-04"},
"success":true
}
A student having parentDetails as a seperate object in the above response.
at my client I did the following :
i had a grid with the below configuration :
var studentRecord = Ext.data.Record.create( [ {
name : 'firstName',
type : 'string'
}, {
name : 'lastName',
type : 'string'
}, {
name : 'middleName',
type : 'string'
}, {
name : 'grade',
type : 'string'
}, {
name : 'kumonLevel',
type : 'string'
}, {
name : 'startTimeSlot',
type : 'string'
}, {
name : 'endTimeSlot',
type : 'string'
}, {
name : 'subject',
type : 'string'
}, {
name : 'dob',
type : 'date'
}, {
name : 'status',
type : 'string'
}, {
name : 'paymentOptions',
type : 'string'
}, {
name : 'parentFirstName',
mapping : 'parentBean.parentFirstName',
type : 'string'
}, {
name : 'parentLastName',
mapping : "parentBean['parentLastName']",
type : 'string'
}, {
name : 'parentMiddleName',
mapping : 'parentBean.parentMiddleName',
type : 'string'
}, {
name : 'parentPhoneNumber',
mapping : 'parentBean.parentPhoneNumber',
type : 'String'
}, {
name : 'parentEmailId',
mapping : 'parentBean.parentEmailId',
type : 'string'
} ]);
var myProxy = new Ext.data.HttpProxy( {
method : 'GET',
url : 'listActiveStudents.do'
});
var studentsListReader = new Ext.data.JsonReader( {
successProperty : 'success',
root : 'studentDetails',
idProperty : 'idStudent'
}, studentRecord);
var studentDS = new Ext.data.Store( {
proxy : myProxy,
autoLoad : true,
totalProperty : 'total',
reader : studentsListReader
});
upon data receiving from the server I did the following :
handler : function() {
studentForm.getForm().submit({
url : 'createStudent.do',
waitMsg : 'Saving Data...',
submitEmptyText : false,
success : function(form, action) {
win.close();
var studentDetail = action.result.studentDetails;
var xyz = new studentDS.recordType(studentDetail, 0);
studentDS.insert(0,xyz);
}
});
}
The problem what I am facing here is :
When the record is inserted the parentDetails are not showing up in the grid. Seems, the mapping is not working properly while inserting. Where as while loading the grid initially it renders perfectly. I created the record well which shows in firefox debbuger with valid values too.
could any one guide me please?

This is a very tricky issue. but I found an easy (but dirty) solution, which you just need to edit the line where you create your record, from this:
var xyz = new studentDS.recordType(studentDetail, 0);
to this:
var xyz = new studentDS.recordType(
studentDS.reader.extractValues(
studentDetail,
studentDS.fields.items,
studentDS.fields.length
), studentDetail.idStudent); //use the idStudent of the studentDetail, so the id of the newly created record equals to your idStudent
And here is why
So after tracing the calling stack, I found an interesting differences between the records you loaded from Store, and the record that you created through your new studentDS.recordType.
Look at the differences:
//This is the record created from Store Load event
dob: Wed Jul 04 2012 00:00:00 GMT+0800 (Malay Peninsula Standard Time)
endTimeSlot: "12:15 AM"
firstName: "Alli"
grade: "A"
kumonLevel: "FK"
lastName: "Alli"
middleName: "Alli"
parentEmailId: "haigopi#gmail.com"
parentFirstName: "Alli"
parentLastName: "Alli"
parentMiddleName: "Alli"
parentPhoneNumber: "3173797945"
paymentOptions: "EFT"
startTimeSlot: "12:00 AM"
status: "ACTIVE"
subject: "MATH"
__proto__: Object
//This is the record created from your studentDS.recordType
dob: "2012-07-04"
endTimeSlot: "12:15 AM"
firstName: "Alli"
grade: "A"
idStudent: 80
kumonLevel: "FK"
lastName: "Alli"
middleName: "Alli"
parentBean: Object
idParent: 68
parentEmailId: "haigopi#gmail.com"
parentFirstName: "Alli"
parentLastName: "Alli"
parentMiddleName: "Alli"
parentPhoneNumber: "3173797945"
__proto__: Object
parentId: 68
paymentOptions: "EFT"
startTimeSlot: "12:00 AM"
status: "ACTIVE"
subject: "MATH"
userId: 1
__proto__: Object
In fact, while you load your data, your JsonStore and JsonReader did a dirty hack to your loaded data. They linearize your data. They move all your data from your parentBean to the root of the record.data, so while rendering the grid, your grid can be rendered correctly.
To know how they render your grid, check the code at Line 827 of GridView.js
meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
Notice how the GridView is capturing the values. They use record.data[column.name] to get the value of each fields, and this is where all your parent* report undefined.
And so to know how they linearize your codes, you can check line 157 of DataReader.js
var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
//where:
//n = your raw json object
//fi = the field items
//fl = the field length
And in fact the new Record they used here is identical with your new studentDS.recordType, with the exception that they extractValues for you on behalf, and clearly you did not do it because it's not obvious to do so.
Got it? Hope the explanation is clear enough.

Related

How to convert a MongoDB document to JSON Object

I am trying to make a post request with the MongoDB document returned from find query, as the request body in NodeJS.But on the server I'm getting the Error : Invalid JSON. Below is the document that I'm trying to POST
{
"_id" : ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount" : 2,
"study" : "cod",
"phase" : "mansa2",
"rhimeTaskId" : "5739a6bec4567f6e737fd3db",
"recordId" : "5726f3cfc4567f6e737fc3ab",
"recordStudy" : "codstudy",
"recordPhase" : "mansa2",
"recordLanguage" : "Punjabi",
"recordScript" : "Latin",
"_state" : "CodingComplete",
"tasks" : [
{
"physician" : ObjectId("5739a6bd3f1b41477570dc78"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Adequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"52 yr male, died of food pipe cancer, suffered pain upper abdomen, investigated,FNAC confirmed Cancer, Put on Chemotherapy, multiple cycles, died at home, had fever with chills occasionally"
]
}
},
{
"physician" : ObjectId("5739a6bd3f1b41477570dc79"),
"stage" : "Coding",
"result" : {
"cod" : "C15",
"feedback" : {
"narrativeLength" : "Inadequate",
"positiveSymptomsIncluded" : "Only Positive",
"certainty" : "High"
},
"keywords" : [
"severe pain abdomen, ultrasonography revealed food pipe cancer, chemotherapy given, died"
]
}
}
],
"__v" : 2
}
and here is the code that I wrote to make the POST request
var MongoClient = require('mongodb').MongoClient;
var request = require('request');
var assert = require('assert');
var cmeprovisioning= 'mongodb://localhost:27017/cmeprovisioning';
MongoClient.connect(cmeprovisioning, function(err, db) {
assert.equal(null, err);
var count=0;
console.log("Connected to cmeprovisioning");
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"
});
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
console.dir(doc);
count=count+1;
request({url: "http://cme.host.net:8081/cme-provisioning/update",
method: "POST",json: true,
headers: {"content-type": "application/json"},
json: doc
},function(e,r,b){
console.log("POST Error "+count+" "+e)
console.log("POST Response "+count+" "+r)
console.log("POST BODY "+count+" "+b)
});
} else {
console.log("Some Error : "+err)
}
});
});
I also tried using JSON.stringify(doc), but still got the Invalid JSON error. Is there a way I can use mongo document returned by the find query and convert it to JSON to make the POST request.
I think those ObjectID is what making it an invalid JSON document.
Here's the actual answer:
If you want to convert a mongo object to JSON object.
There's a utility method in every mongo object toJSON
So you can simply do mongoResponseObject.toJSON() on the response object.
e.g.
Products.findById(id).then(res => {
const jsonRes = res.toJSON();
// Here jsonRes is JSON
})
Alternatively you can directly get the JSON object by using the .lean() like this.
Products.findById(id).lean().then(res => {
// Here res is JSON
})
you need to convert object id to string ie.
var result = {
"_id": ObjectId("5739a6bf3f1b41477570dc89"),
"taskCount": 2,
"study": "cod"
};
//now convert to string
result=result._id.toString();
//now you can use the result
Try this,
var cursor =db.collection('rhimeReport').find(
{"study":"cod","phase":"mansa2","recordStudy":"codstudy",
"recordPhase":"mansa2","_state":"CodingComplete"});
cursor.toString();
......
Hope this help.
Try this in robomongo
var cursor = db.getCollection('X').find({},{})
while(cursor.hasNext()) {
print(JSON.stringify(cursor.next()))
}

posting objectId in postman

I'm trying to post this json to an API using postman
{
"order" : [{ "mealId": 562b2649b2e70464f113c04d, "quantity": 4}],
"service_id" : 562b2649b2e70464f113c04d,
"dest" : "Allabama",
"active": false
}
but I keep getting this error
SyntaxError: Unexpected token b
at Object.parse (native)
at parse (C:\nodeprojects\foodDelivery\node_modules\body-parser\lib\types\json.js:88:17)
at C:\nodeprojects\foodDelivery\node_modules\body-parser\lib\read.js:108:18
at invokeCallback (C:\nodeprojects\foodDelivery\node_modules\body-parser\node_modules\raw-body\index.js:262:16)
at done (C:\nodeprojects\foodDelivery\node_modules\body-parser\node_modules\raw-body\index.js:251:7)
at IncomingMessage.onEnd (C:\nodeprojects\foodDelivery\node_modules\body-parser\node_modules\raw-body\index.js:308:7)
at IncomingMessage.emit (events.js:104:17)
at _stream_readable.js:908:16
at process._tickCallback (node.js:355:11)
its a nodejs api with mongoose.
This is the schema for the json object
var mongoose = require('mongoose');
var OrdersSchema = new mongoose.Schema({
order : [{ mealId: mongoose.Schema.Types.ObjectId, quantity: Number}],
service_id : mongoose.Schema.Types.ObjectId,
dest : String,
orderTime : {type:Date, default:Date.now},
completeTime : {type:Date, default:Date.now},
active: Boolean,
});
So in short the problem is when I try to pass the ObjectId, It stops reading after the "562" and sees the 'b' as an illegal character.
You must quote the strings:
{
"order" : [{ "mealId": "562b2649b2e70464f113c04d", "quantity": 4}],
"service_id" : "562b2649b2e70464f113c04d",
"dest" : "Allabama",
"active": false
}
receive the _id object as a string and not as ObjectId,
when you got this id create new mongo.driver ObjectId
public async Task<IHttpActionResult> PostExample(string idinstring)
{
ObjectId d=new ObjectId(idinstring);
}

ExtJS 4 MVC, Get Checkbox value integer instead of bool

I'm using a form to edit Model. I receive data in JSON. Here's my problem:
I receive data for Checkbox only in INT: 1 or 0, I cannot change it. JSON:
{ "checkboxValue": 1 }
This field in ExtJS model is defined as INT type. Model:
{name: "checkboxValue", type: Ext.data.Types.INT},
then I set values to form this way:
formCmp.loadRecord(loadedStore.getAt(0));
and my checkbox is set correctly: when I receive 1 it's checked, 0 - unchecked.
But when I try to save record and send data to server this way:
form.updateRecord(form.getRecord());
record.save();
I need Checkbox to have also INT value - 1 or 0. But it has only BOOL value - true or false so when JSON is sent that value is NaN.
{
"checkboxValue": NaN
}
I think, that function .updateRecord(..) go through all elements and when it gets to checkbox it tries to get value, and the value is BOOL
Does anybody know how to make checkbox' output value INT?
Ext.form.Basic.updateForm uses getFieldValues method to retrieve new data for the updated record, while getFieldValues method returns only boolean values for checkboxes regardless of such properties as inputValue or uncheckedValue. So I would use convert function for the model's field to transform provided boolean value into an integer in a way like that:
Ext.define('MyModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'flag',
type: 'int',
convert: function (v, record) {
return typeof v === 'boolean' ? (v === true ? 1 : 0) : v;
}
}
],
...
});
Here is a complete jsfiddle
I think it can be done with some simple overrides
Ext.create('Ext.form.Panel', {
bodyPadding: 10,
width: 300,
title: 'Pizza Order',
items: [
{
xtype: 'fieldcontainer',
fieldLabel: 'Toppings',
defaultType: 'checkboxfield',
items: [
{
boxLabel : 'Topping?',
name : 'topping',
id : 'checkbox1',
// include these two properties in your checkbox config
uncheckedValue: 0,
setValue: function(checked) {
var me = this;
arguments[0] = checked ? 1 : me.uncheckedValue;
me.callParent(arguments);
return me;
}
}
]
}
],
renderTo: Ext.getBody()
});

ExtJS AJAX returned JSON object

I have an AJAX call inside an ExtJS script, but I'm not sure how to take the returned JSON object and assign it to a variable for use on the page. I'm basically taking a hardcoded extJS script and puting in JSON from database. Here is what I need to do
Get a variable from this AJAX call:
Ext.onReady(function () {
Ext.Ajax.request({
url: '/xxx/clienttool/components/Client-Tool.cfc?method=getResources&returnformat=json',
params: {
accountID: 463
},
success: function(response){
var text = response.responseText;
// process server response here
}
});
and assign it so these values aren't hardcoded:
// Store holding all the resources
resourceStore : Ext.create("Sch.data.ResourceStore", {
model : 'Sch.model.Resource',
data : [
{Id : 'MadMike', Name : 'Mike'},
{Id : 'JakeTheSnake', Name : 'Jake'},
{Id : 'KingFu', Name : 'King'},
{Id : 'BeerBrian', Name : 'Brian'},
{Id : 'LindaAnderson', Name : 'Linda'},
{Id : 'DonJohnson', Name : 'Don'},
{Id : 'KarenJohnson', Name : 'Karen'},
{Id : 'DougHendricks', Name : 'Doug'},
{Id : 'PeterPan', Name : 'Peter'}
]
}),
Here's the whole thing:
Ext.onReady(function () {
App.SchedulerDemo.init();
});
App.SchedulerDemo = {
// Initialize application
init : function () {
Ext.define('Event', {
extend : 'Sch.model.Event',
fields : [
{name : 'Title'},
{name : 'Type'}
]
});
//ajax call to get resources for this accountID
Ext.Ajax.request({
url: '/xxxx/clienttool/components/Client-Tool.cfc?method=getResources&returnformat=json',
params: {
accountID: 463
},
success: function(response){
getResources = response.responseText;
// process server response here
}
});
//alert(getResources);
var zoneStore = Ext.create('Ext.data.JsonStore', {
model : 'Sch.model.Range',
data : [
{
// Nice 2 hour lunch
StartDate : new Date(2011, 11, 9, 12),
EndDate : new Date(2011, 11, 9, 14),
Cls : 'lunch-style'
}
]
});
var sched = Ext.create("Sch.panel.SchedulerGrid", {
height : ExampleDefaults.height,
width : ExampleDefaults.width,
rowHeight : 40,
eventBarTextField : 'Title',
viewPreset : 'hourAndDay',
startDate : new Date(2011, 11, 9, 7),
endDate : new Date(2011, 11, 9, 20),
orientation : 'vertical',
constrainDragToResource : false,
eventBarIconClsField : 'Type',
snapToIncrement : true,
//constrainDragToResource : true,
eventResizeHandles : 'end',
viewConfig : {
// Experimental for CSS3 enabled browsers only
eventAnimations : true
},
// Store holding all the resources
resourceStore : Ext.create("Sch.data.ResourceStore", {
model : 'Sch.model.Resource',
data :
[
{Id : 'MadMike', Name : 'Mike'},
{Id : 'JakeTheSnake', Name : 'Jake'},
{Id : 'KingFu', Name : 'King'},
{Id : 'BeerBrian', Name : 'Brian'},
{Id : 'LindaAnderson', Name : 'Linda'},
{Id : 'DonJohnson', Name : 'Don'},
{Id : 'KarenJohnson', Name : 'Karen'},
{Id : 'DougHendricks', Name : 'Doug'},
{Id : 'PeterPan', Name : 'Peter'}
]
}),
If the only purpose of the AJAX request is to retrieve data for your grid's store, I would ditch it altogether and simply define an AJAX proxy on your store. It will not only accomplish the same initial objective (e.g., getting data for your store), but will also handle creating model instances of your data and binding the store to your grid.
I would suggest checking out the docs for the Store, as well as the grid examples in the documentation.

Mongoose .populate() only showing 1 document

I am trying to output just the hometeam name's to the page so that I can try to understand how to work with my code better. It is only printing one team to the page, and it is printing all the details of that team to the page, whereas I only want it to print one part.
This is my code, I want it to print the name's of each hometeam to the page
app.get('/home', function(req, res) {
Match.findOne({}).populate('hometeam.name').exec(function(err, teams){
util.log(teams);
res.send(teams);
});
});
But when I load the page all I get is the first piece of data from this list of Matches
[
{
"hometeam": "5106e7ef9afe3a430e000007",
"_id": "5113b7ca71ec596125000005",
"__v": 0,
"key": 1360246730427
},
{
"hometeam": "5113c13e0eea687b28000001",
"_id": "5113e951354fe70330000001",
"__v": 0,
"key": 1360259409361
},
{
"hometeam": "5113c13e0eea687b28000001",
"_id": "5113e999354fe70330000002",
"__v": 0,
"key": 1360259481412
}
]
Also, if I try to put util.log(teams.hometeam.name) I get the following:
TypeError: Cannot call method 'toString' of undefined
But I would want it to be able to print the name which belongs to hometeam here. As hometeam is just the objectId of a Team in my database, am I missing something with the DBreferencing here?
Update:
Team Schema
var Team = new Schema({
'key' : {
unique : true,
type : Number,
default: getId
},
'name' : { type : String,
validate : [validatePresenceOf, 'Team name is required'],
index : { unique : true }
}
});
module.exports.Schema = Team;
module.exports.Model = mongoose.model('Team', Team);
Match Schema
var Team = require('../schemas/Team').Schema;
var Match = new Schema({
'key' : {
unique: true,
type: Number,
default: getId
},
'hometeam' : { type: Schema.ObjectId, ref: 'Team' },
'awayteam' : { type: Schema.ObjectId, ref: 'Team' }
});
module.exports = mongoose.model('Match', Match);
Populate takes the property name of the property you are trying to retrieve. This means that you should use 'hometeam' instead of 'hometeam.name'. However, you want to retrieve the name of the team so you could filter for that. The call would then become..
Match.findOne({}).populate('hometeam', {name: 1}).exec(function(err, teams)
Now you have a property called 'hometeam' with in that the name. Have fun :)
EDIT
Showing how to have a single mongoose instance in more files to have correct registration of schemas.
app.js
var mongoose = require('mongoose');
var Team = require('./schemas/team-schema')(mongoose);
var Match = require('./schemas/match-schema')(mongoose);
// You can only require them like this ONCE, afterwards FETCH them.
var Team = mongoose.model('Team'); // LIKE THIS
schemas/match-schema.js
module.exports = function(mongoose) {
var Match = new mongoose.Schema({
'key' : {
unique: true,
type: Number,
default: getId
},
'hometeam' : { type: mongoose.Schema.ObjectId, ref: 'Team' },
'awayteam' : { type: mongoose.Schema.ObjectId, ref: 'Team' }
});
return mongoose.model('Match', Match);
};
schemas/team-schema.js
module.exports = function(mongoose) {
var Team = new mongoose.Schema({
'key' : {
unique : true,
type : Number,
default: getId
},
'name' : { type : String,
validate : [validatePresenceOf, 'Team name is required'],
index : { unique : true }
}
});
return mongoose.model('Team', Team);
};