I have my route below that takes the form data and tries to input the page and archive into an existing name that is already in the mongodb. My form data is being sent correctly as I can see from my console.log.
Now I need to insert the page name and archive name where it equals name. Whether it already has data or not. They are already setup with array in the schema. You can see my schema below
Any ideas on how to get this setup?
router.post('/add-page', function(req, res, next){
if(req.body.name && req.body.page && req.body.archive){
//create object with form input
var pageData = {
client: req.body.name,
page: req.body.page,
archive: req.body.archive
};
console.log(pageData);
//insert data
Page.then(function(db){
delete req.body._id;
db.collection('pages').insertOne();
});
return res.render('index', { title: 'Home' });
}else{
var err = new Error('All fields required.');
err.status = 400;
return next(err);
}
});
var ClientSchema = new mongoose.Schema({
client: {
type: String,
required: true,
trim: true,
unique: true,
},
page: {
type: [],
trim: true,
},
archive: {
type: [],
trim: true,
}
});
Related
Currently, I created a keystone model as following format:
var keystone = require('keystone');
var SiteSettings = new keystone.List('SiteSetting', {
map: { name: 'siteName' },
nocreate: true,
noedit: false,
nodelete: true,
singular:'SiteSetting',
plural: 'SiteSetting',
});
SiteSettings.add({
siteName: { type: String, required: true },
contactNumber: { type: String, required: false },
facebookGroupUrl: { type: String, required: false },
googlePlusUrl: { type: String, required: false }
});
SiteSettings.register();
Then I went to keystone back-end, created a new Site Setting object.
And on my default template, i am using a partial view like this:
<body>
<main>
{{>header}}
{{>footer}}
</main>
</body>
And this is my footer partial:
<div class="row">//I want to print my site name here</div>
But I have no idea how can retrieve model data without a route. Because it's a partial view.
Any idea ? what should I do ? Is there anything I can do in middleware.js
Thank you everyone,.
Yes, you can load the global site settings in a middleware.
// routes/middleware.js
exports.initLocals = (req, res, next) => {
const { locals } = res;
// Load site settings from db
keystone.list('SiteSettings').model.findOne().exec((err, result) => {
locals.siteSetting = result;
next(err);
});
};
// routes/index.js
const { initLocals } = require('./middleware');
keystone.pre('routes', initLocals);
Then you can use the siteName in the footer.
<div class="row">{{ siteSetting.siteName }}</div>
I am working on a REST API using Node, Express and Mongoose. Everything works perfectly when I update the base model. But when I try to update the discriminator object sportEvent in this case, it doesn't work.
Event.js - Event data model has a base schema common for all the collections with a discriminator for additional detail for that collection.
// base schema for all the events
// includes basic detail for all the events
const eventSchema = new Schema({
//title for the event
title: {
type: String,
required: true
},
//description for the events
description: {
type: String,
required: true
},
//event type for the event. such as Music, Sports, Expo, Leisure
eventType: {
type: String,
required: true,
}
}, { discriminatorKey: 'eventType' });
//sport event model for extending the basic event model
const sportEvent = Event.discriminator("sports", new Schema({
sportEvent: {
//sport name. for eg: cricket, football, etc
sportName: {
type: String,
required: true
},
//first team name
firstTeam: {
type: String,
required: true
},
//second team name
secondTeam: {
type: String,
required: true
},
}
}));
EventController.js - has a PUT method for updating the collection. Here is a code snippet.
//for updating the event added a PUT method in /event route
router.put('/events/:eventId', function(req, res, next){
//getting the event id form the url
eventId = req.params.eventId;
//checking the provided event id is a valid mongodb _id object or not
if(objectId.isValid(eventId)){
Event.findOneAndUpdate({_id: eventId}, {$set: req.body}, {new: true, runValidators: true}, function(err, event){
if(err) {
next(err);
}
sendResponse(res, "Event Successfully Updated", event);
});
} else {
//sending a bad request error to the user if the event id is not valid
sendError(res, 400, "Invalid Event ID");
}
});
Ensure the discriminator key is present in the update object, or as an argument to the update function, write a switch case based on discriminator key, call update on the specific Schema type
callback = function(err, doc){
if(err) console.log(err)
console.log(doc)
};
var id = ObjectId("5a75d22e6dabf3102c059f56");
var update = {
title : 'title-name',
eventType : 'sports' ,
sportEvent : {
firstTeam : 'first-name',
secondTeam : 'second-name',
sportName : 'sport-name'
}
};
switch(update.eventType){
case 'sports':
SportEventSchema.findByIdAndUpdate(id, {$set : update}, {new : true, upsert : false}, callback)
break;
case 'games':
GameEventSchema.findByIdAndUpdate(id, {$set : update}, {new : true, upsert : false}, callback)
break;
default:
Event.findByIdAndUpdate(id, {$set : update}, {new : true, upsert : false}, callback);
break;
}
output : update for a sports event type
Mongoose: events.findAndModify({ eventType: 'sports', _id: ObjectId("5a75d22e6dabf3102c059f56") }, [], { '$set': { title: 'title-name', eventType: 'sports', sportEvent: { firstTeam: 'first-name', secondTeam: 'second-name', sportName: 'sport-name' } } }, { new: true, upsert: false, remove: false, fields: {} })
{ sportEvent:
{ firstTeam: 'first-name',
secondTeam: 'second-name',
sportName: 'sport-name' },
eventType: 'sports',
_id: 5a75d22e6dabf3102c059f56,
title: 'title-name',
description: 'desc',
__v: 0 }
As of Mongoose 6, you can modify the value of the discriminator key by using the overwriteDiscriminatorKey option:
//for updating the event added a PUT method in /event route
router.put('/events/:eventId', function (req, res, next) {
//getting the event id form the url
eventId = req.params.eventId;
//checking the provided event id is a valid mongodb _id object or not
if (objectId.isValid(eventId)) {
Event.findById(eventId, function (err, event) {
Event.replaceOne(
{ _id: eventId },
{ ...event.toObject(), ...req.body },
{
overwriteDiscriminatorKey: true,
new: true,
runValidators: true,
},
function (err, event) {
if (err) {
next(err);
}
sendResponse(res, 'Event Successfully Updated', event);
}
);
});
} else {
//sending a bad request error to the user if the event id is not valid
sendError(res, 400, 'Invalid Event ID');
}
});
What I am trying to do is create a form with meteor-autoform that will redirect the user to a newly generated route on submit. My thought process is that I can take the submissions _id and use it for an iron:router parameter. What I have so far looks as followed:
Creation of Form
Submits = new Meteor.Collection('Submits');
Submits.allow({
insert: function(username, doc){
return !!username;
}
});
SubmitSchema = new SimpleSchema({
title: {
type: String,
label: "Title"
},
subject:{
type: String,
label: "Subject"
},
summary:{
type: String,
label: "Summary"
},
author:{
type: String,
label: "Author",
autoValue: function() {
return this.userId
},
autoform: {
type: "hidden"
}
},
createdAt: {
type: Date,
label: "Created At",
autoValue: function(){
return new Date()
},
autoform: {
type: "hidden"
}
}
});
Submits.attachSchema( SubmitSchema );
Routing
Router.route('/submit', {
layoutTemplate: 'submitLayout',
waitOn: function() { return Meteor.subscribe("Submits"); },
loadingTemplate: 'loading'
});
Router.route('/submit/:_id', {
name: 'formDisplay',
data: function() {
return Submits.findOne({this.params._id});
}
});
And then I just have the average publish and find calls. My issues are I'm not sure how to perform the redirect on submit, and I am not sure how to display the form results on the newly generated route.
Any help would be appreciated.
I was able to do it by adding an autoform.hook and changing my routing a bit.
Autoform hook:
AutoForm.addHooks('insertSubmit', {
onSuccess: function(doc) {
Router.go('formDisplay',{_id: this.docId});
}
})
Routing:
Router.route('/submit/:_id', {
name: 'submitLayout',
data: function() { return Products.findOne(this.params._id);}
});
I got this information from this post:
Route to the new data submitted by Meteor autoform using iron router?
Mongoose findOne function call does nothing and I am in trouble again. Callback is not never returned...
schema.js file:
var schemaSizeGroup = new Schema({
sizeGroupId : {type: Number, required: true, index: true, index: { unique: true }}
,sizeGroupName : {type: String, required: true, trim: true, index: { unique: true }}
,sizeGroupValues : {type: String, required: true, trim: true }
,active : {type: Boolean, default: true }
}, { collection: 'sizegroup' }).index({sizeGroupId : 1});
module.exports ={
SizeGroup : mongoose.connection.model('SizeGroup', schemaSizeGroup),
}
index.js file:
findDocumentById : function(sGroupId, callback){
winston.info(" Trying to select!");
model.SizeGroup.findOne( {sizeGroupId : sGroupId} ,function(err, sGroup) {
winston.info(" Select done:");
winston.info(JSON.stringify(sGroup,null,2));
if(!err) {
if(!sGroup) {
callback(new Error(" No SizeObject Found for Id:" + sizeGroupId));
} else { callback(null, sGroup); }
}
else {
callback(err);
}
});
}
}
selectin data using mongo client returns correct data nicely:
db.sizegroup.find({sizeGroupId : 6});
When using mongoose.set('debug', true) output looks like:
Mongoose: sizegroup.findOne({ sizeGroupId: 6 }) { fields: undefined }
I have active mongoose connection, because all the previous insert statements have been successful.
Am I doing something wrong?
It was a callback problem in program flow. Clear case of pure stupidity....
I have a statemodel like this:
var stateModel = {
StateId: ko.observable(0),
StateName: ko.observable('').extend({ required: true }).extend({ pattern: { message: 'Enter only Text', params: '^[a-zA-Z ]*$'} }),
ShortName: ko.observable('')
.extend({ required: true })
.extend({ pattern:
{ message: 'Enter only Text', params: '^[a-zA-Z ]*$'}
}),
IsActive: ko.observable(true),
CountryId: ko.observable().extend({ required: true })
}
And i am posting it by converting into json string by following :
var args=JSON.stringify({argBO: jQuery.parseJSON(ko.toJSON(self.StateModel))});
after this i want to push this to my observable array StateList() ,so i am converting it into objects and pushing it like:
var model = jQuery.parseJSON(ko.toJSON(self.StateModel));
self.StatesList.push(model);
My args will look like this:
{"argBO":
{ "StateId":0,
"StateName":"jjhj",
"ShortName":"jjj",
"IsActive":true,
"CountryId":8,
"errors":[],
"CountryName":"Antigua and Barbud"
}
}
If i could remove the argBO From above i can directly push the 'args' rather than self.StateModel, again by converting args into objects.
self.StatesList.Push(args);
I tried like this :
jQuery.parseJSON(args(jQuery.parseJSON(argBO)))
jQuery.parseJSON(args(jQuery.parseJSON[argBO]))
jQuery.parseJSON(args[argBO]))
But none of them working please anybody tell me!!
You can try this:
var JSONargs = jQuery.parseJSON(ko.toJSON(self.StateModel));
OR if you use the knockout.mapping.js plugin:
var JSONargs = ko.mapping.toJS(self.StateModel);
When you want to post it, you can do:
$.ajax({data: JSON.stringify({ argBO: JSONargs });
And then your push could be like
self.StatesList.Push(JSONargs);