Reputation: 340
I'm working on a MEAN project with handlebars. I originally just used the data direct from my database queries and pushed it to my handlebars views. I've had to stop this as i want to do some data transformation, I also heard it is better security practice as it strips away data you may not intend to pass.
Anyway, I can't get the mapping correct for a nested data set.
My schema is below;
var approverSchema = mongoose.Schema({
name: String,
status: String,
comment: String,
date: Date
});
var taskSchema = mongoose.Schema({
name: String,
description: String,
owner: String,
businessUnit: String,
status: String, // draft, pending, approved, rejected
approvalDue: Date,
submitted: Date,
approved: Date,
approvers: [approverSchema]
});
and my code is;
'use strict';
var Task = require('../models/task.js');
exports.home = function (req, res, next) {
/* get tasks
------------------------------------------------------------------ */
Task.find({
owner: signedOnUser
}, function (err, result) { //callback function
if (err) {
return console.log(err);
}
var taskContext = {
tasks: result.map(function(result){
return {
name: result.name,
businessUnit: result.businessUnit,
status: result.status,
approvalDue: result.getDisplayDate(),
//approvers: result.approvers
approvers: result.approvers.map(function(result){
return {
name: result.approvers.name
};
})
};
})
};
res.render('home', {
taskContext: taskContext,
});
});
};
I'm pretty sure my issue is in the function(result)
, I'm passing the nested map, but I just can't seem to get it right.
Upvotes: 1
Views: 7675
Reputation: 10864
I'm guessing you made a typo in the the map function:
'use strict';
var Task = require('../models/task.js');
exports.home = (req, res, next) => {
/* get tasks
------------------------------------------------------------------ */
Task.find({
owner: signedOnUser
}, function (err, results) { //callback function
if (err) {
return console.log(err);
}
const taskContext = {
tasks: results.map((task) => {
return {
name: task.name,
businessUnit: task.businessUnit,
status: task.status,
approvalDue: task.getDisplayDate(),
//approvers: task.approvers
approvers: task.approvers.map((approver) => {
return {
name: approver.name
};
})
};
})
};
res.render('home', {
taskContext: taskContext,
});
});
};
In my code, I used unique names for the argument passed to each map function in order to prevent conflicting names.
In the second map
function I called the name
property directly from the approver
argument instead of task.approvers.name
.
Upvotes: 1
Reputation: 1197
John Kennedy answered the question, but you can clean up the code a bit using object deconstructing. It sounds like you are working server side, so you can use newer JavaScript syntax.
const taskContext = {
tasks: result.map(({name, businessUnit, status, getDisplayDate, approvers}) =>
({name,
businessUnit,
status,
approvalDue: getDisplayDate(),
approvers: approvers.map(({name}) => {name})})
);
The deconstructing syntax takes out the properties from the object. Then you can just return them like name
, businessUnit
and status
and they will be set with name:name
, businessUnit:businessUnit
and status:status
, for approvalDue
and approvers
we need to do a bit of extra work.
Also it is probably a good idea to change approvers: approvers.map(({name}) => {name})
to approvers: approvers.map(({name}) => name)
, because now its an Array
of strings which allowes you to use Array.indexOf
and Array.includes
instead of Array.find
etc.
Upvotes: 0