PDA

View Full Version : Cannot fully post nested json from ExtJS 4 to Mongoose, using assication model



felixfang
28 May 2013, 5:36 AM
Good afternoon,

I am using ExtJS+mongoDB to implement an app. I use node.js as the server and express module to create REST api.
In details, I use: ExtJS 4.1.3 + mongoose 1.2.17 + express 1.2.17 + mongodb 2.4, running on Node.js v0.10.3.

The codes ExtJS part(orgnised in MVC):

The Model part contains two models, PvdcPrice and PvdcPriceDetails, they have "hasMany" relationship.
PvdcPrice.js:
Ext.define('App.model.PvdcPrice', {
extend : 'Ext.data.Model',
fields : [{
name : '_id',
type : 'Number'
}, {
name : 'Type',
type : 'string'
}, {
name : 'MaxDiscount',
type : 'Number'
}],
hasMany : [{
name : 'prices',
model : 'App.model.PvdcPriceDetail',
associationKey : 'prices'
}],
proxy : {
type : 'rest',
url : '/pvdcprices',
reader : {
type : 'json',
root : 'data',
successProperty : 'success'
}
}
});
PvdcPriceDetail.js:
Ext.define('App.model.PvdcPriceDetail', {
extend : 'Ext.data.Model',
fields : [{
name : 'ID',
type : 'Number'
}, {
name : 'Location',
type : 'string'
}, {
name : 'Edition',
type : 'string'
}, {
name : 'MonthlyPrice',
type : 'Number'
}, {
name : 'OneTimePrice',
type : 'Number'
}
]
});
The Controller part, as it is too long I put only the store creating part here:
var pvdcPrice = Ext.create('Ext.data.Store', {
model : "App.model.PvdcPrice",
data : [{
"_id" : 1,
"Type" : "pvdc",
"MaxDiscount" : "0"
}]
});
var priceInfo = pvdcPrice.first();
var pvdcPriceDetails = priceInfo.prices();
pvdcPriceDetails.add({
'ID' : 1,
'Location' : 'SNJ',
'Edition' : 'Basic',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPriceDetails.add({
'ID' : 2,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPriceDetails.add({
'ID' : 3,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
});
pvdcPrice.sync();

var record = pvdcPrice.first();
console.log(record.get('Type'));
record.prices().each(function(r) {
console.log(r.get('Location'));
console.log(r.get('Edition'));
});

The Node.js part, the server script is app.js:
var express = require('express'),
app = module.exports = express();
// MongoDB
var mongoose = require('mongoose'),
db = mongoose.connect('mongodb://127.0.0.1/IaaSDB'),
//create sub schema of pvdc price schema
PriceDetailSchema = new mongoose.Schema({
ID: Number,
Location: String,
Edition: String,
MonthlyPrice: Number,
OneTimePrice: Number
}),
//create the Pvdc price info Model using the 'pvdcPrice' collection as a data-source
PvdcPrice = mongoose.model('pvdcPrice', new mongoose.Schema({
Type: String,
MaxDiscount: String,
prices: [PriceDetailSchema]
}));

// Configuration
app.configure(function () {
app.use(express.bodyParser());//parse JSON into objects
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/IaaSPriceTool'));
});

app.configure('development', function () {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});

app.configure('production', function () {
app.use(express.errorHandler());
});

// Routes
app.get('/', function (req, res) {
res.redirect('/index.html');
});


/*
Pvdc Price Information CRUD web service
*/
app.get('/pvdcprices', function (req, res) {
PvdcPrice.find({}, function (err, pvdcprices) {
res.contentType('json');
res.json({
success: true,
data: pvdcprices
});
});
});
app.get('/pvdcprices/:id', function(req, res){
PvdcPrice.find({_id: req.params.id}, function (err, pvdcPrices) {
res.contentType('json');
res.json({
success: true,
data: pvdcPrices
});
});
});
app.post('/pvdcprices', function (req, res) {
console.log("[200] " + req.method + " to " + req.url);
console.log(req.body);

var newPriceInfo = new PvdcPrice();
var newPriceInfoData = req.body;
//remove the id which the client sends since it is a new pvdc price
delete newPriceInfo['_id'];
newPriceInfo.set(newPriceInfoData);
newPriceInfo.save(function (err, pvdcPrice) {
res.contentType('json');
res.json({
success: !err,
data: pvdcPrice
});
});
});

app.listen(3000);
console.log("Express server listening on port %d in %s mode", 3000, app.settings.env);

After then, I use firebug to debug the frontend, I can see from the browser console that the contend of pvdc price is printed:
44048

This means that the association model in ExtJS works so that I can see the printed pvdcPrice content. The json structure in ExtJS should be:

{
"data" :{
"_id" : 1,
"Type" : "pvdc",
"MaxDiscount" : "0",
"prices" : [{
'ID' : 1,
'Location' : 'SNJ',
'Edition' : 'Basic',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
},{
'ID' : 2,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
},{
'ID' : 3,
'Location' : 'ATL',
'Edition' : 'Standard',
'MonthlyPrice' : 906,
'OneTimePrice' : 777
}]
}
}

But in the console of node.js part, when I print the request body of post in node.js, it is:
[200] POST to /pvdcprices?_dc=1369734975208
{ _id: 1, Type: 'pvdc', MaxDiscount: 0, id: null }

That is to say only the content of data is posted to server, the sub content under "prices" part is missing.
I checked the database, there is nothing inserted.

Could someone point out what causes the missing of information during the post process? Really appreciate any help.

felixfang
28 May 2013, 7:36 AM
Then I tried the GET function, first it didn't work. Then I change the collection name from "pvdcPrices" to "pvdcprices" and update mongoose model defining in app.js. Now GET works, which means I can get nested schema from mongodb and put it into Store in ExtJS.

But the POST still didn't work, after I changed the collection name.

Any help?