Passing id between router and collection, Meteor - javascript

I am trying to use Session.set() in my router and Session.get() with autoValue in my schema, but Session.get() is undefined within my schema scope. How can I pass the value of the current id (as it is appended to the end of my URL) to autoValue in my schema?
//collections/singleDetails.js
singleDetails = new Meteor.Collection('singleDetails');
singleDetails.attachSchema(new SimpleSchema({
location: {
type: String,
label: 'location',
max: 200,
optional: true
},
number: {
type: Number,
label: 'number of attendees',
max: 2000,
optional: true
},
occasion: {
type: String,
label: 'occasion for speech'
},
speakerId: {
type: String,
autoValue: function(){
Session.get('pathId');
}
}
}));
And here is the router
//client/views/singleDetails.js
Router.route('singleDetails', {
path: '/speakers/singleDetails/:_id',
template: 'singleDetails',
data: function(){
return Speakers.findOne({_id: this.params._id});
},
onBeforeAction: function(){
console.log(this.params._id);
Session.set('pathId', this.params._id);
this.next();
}
});
Template.singleDetails.helpers({
singleDetails: function(){
return singleDetails.find({});
}
});

Related

Mongoose create method ignores variable, but not hard coded data

Can someone lead me in the right direction? I'ven been stuck on this a few days. I'm using Express and Mongoose. Here is my controller,
module.exports.addPoll = function(req,res) {
var optionsArray = [];
var row = [];
req.body.option1.forEach( function(value) {
optionsArray.push('{"v":"' + value + '"},{"v":0}');
});
var beg = '{"c":[';
var end = ']}';
var whole = beg.concat(optionsArray, end);
Pol.create({
cols: [{label: "options", type: "string"}, {label: "quantity", type:
"number"}],
rows: whole,
title: req.body.heading
}, function(err, poll) {
if (err) {
sendJSONresponse(res, 400, err);
} else {
sendJSONresponse(res, 201, poll);
console.log(whole);
}
});
}
When i create the document the rows property is empty. It ignores the variable that has the data and looks like this.
{"__v":0,"rows":{"c":[]},"title":"What is tomorrow","_id":"59826915c7a0186940e8431c","cols":[{"label":"options","type":"string"},{"label":"quantity","type":"number"}]}
Here is what it looks like when it logs and if replace the variable withi this, it works perfectly fine. I don't get it.
[{"c":[{"v":"Monday"},{"v":"0"},{"v":"Tuesday"},{"v":"0"}]}]
Here is my schema.
var rowsSchema = new mongoose.Schema({
c: [{
v: {
type: String,
required: true
},
_id:false
},
{
v:{
type:Number,
required: true
},
_id:false
}],
_id: false
})
var pollSchema = new mongoose.Schema({
cols: [{
label: {
type: String,
required: true
},
type: {
type: String,
required: true
},
_id: false
},
{
label: {
type: String,
required: true
},
type: {
type: String,
required: true
},
_id:false
}],
rows: rowsSchema,
title: {type: String, required:true, _id:false}
})

fileLink is not allowed by schema

I'm trying to use Simple Schema in my current Meteor React project but for some reason I can't get it to work.
This is my schema:
Comments.schema = new SimpleSchema({
city: {
type: String,
label: 'The name of the city.'
},
person: {
type: String,
label: 'The name of the person.'
},
location: {
type: String,
label: 'The name of the location.'
},
title: {
type: String,
label: 'The title of the comment.'
},
content: {
type: String,
label: 'The content of the comment.'
},
fileLink: {
type: String,
regEx: SimpleSchema.RegEx.Url,
label: 'The url of the file.'
},
createdBy: {
type: String,
autoValue: function(){ return this.userId },
label: 'The id of the user.'
}
});
And this is my insert:
createSpark(event){
event.preventDefault();
const city = this.city.value;
const person = this.person.value;
const location = this.location.value;
const title = this.title.value;
const content = this.content.value;
const fileLink = s3Url;
insertComment.call({
city, person, location, title, content, fileLink
}, (error) => {
if (error) {
Bert.alert(error.reason, 'danger');
} else {
target.value = '';
Bert.alert('Comment added!', 'success');
}
});
}
I'm saving the value I get back from amazon in a global variable called s3Url. I am able to console.log this variable without a problem but when I want to write it to the database I am getting a "fileLink is not allowed by schema" error.
Anyone see what I am doing wrong?
Here is my comments.js file:
import faker from 'faker';
import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import { Factory } from 'meteor/dburles:factory';
export const Comments = new Mongo.Collection('comments');
Comments.allow({
insert: () => false,
update: () => false,
remove: () => false,
});
Comments.deny({
insert: () => true,
update: () => true,
remove: () => true,
});
Comments.schema = new SimpleSchema({
city: {
type: String,
label: 'The name of the city.'
},
person: {
type: String,
label: 'The name of the person.'
},
location: {
type: String,
label: 'The name of the location.'
},
title: {
type: String,
label: 'The title of the comment.'
},
content: {
type: String,
label: 'The content of the comment.'
},
fileLink: {
type: String,
regEx: SimpleSchema.RegEx.Url,
label: 'The url of the file.'
},
createdBy: {
type: String,
autoValue: function(){ return this.userId },
label: 'The id of the user.'
}
});
Comments.attachSchema(Comments.schema);
And my methods.js file:
import { Comments } from './comments';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { rateLimit } from '../../modules/rate-limit.js';
export const insertComment = new ValidatedMethod({
name: 'comments.insert',
validate: new SimpleSchema({
city: { type: String },
person: { type: String, optional: true },
location: { type: String, optional: true},
title: { type: String },
content: { type: String },
fileLink: { type: String, regEx: SimpleSchema.RegEx.Url },
createdBy: { type: String, optional: true }
}).validator(),
run(comment) {
Comments.insert(comment);
},
});
rateLimit({
methods: [
insertComment,
],
limit: 5,
timeRange: 1000,
});
While working a bit more on it I noticed some things I was doing wrong.
1. I didn't have the right value for my simple schema set up.
2. Some problems have to do with the fact the url has white spaces in it. What can I do to fix this?
3. The current error I am getting is: "Exception in delivering result of invoking 'comments.insert': ReferenceError: target is not defined."
While working a bit more on it I noticed some things I was doing wrong. 1. I didn't have the right value for my simple schema set up. 2. Some problems have to do with the fact the url has white spaces in it. What can I do to fix this? 3. The current error I am getting is: "Exception in delivering result of invoking 'comments.insert': ReferenceError: target is not defined."
Thanks #Khang

How do you automatically assign a field in a Meteor simple schema to a variable as soon as its declared?

I am making a simple schema in meteor with the Aldeed packages, and for the schema, I need to have it so one of the values is not influenced by user input, but is automatically assigned to variable. Here is an example of a schema:
LobbySchema = new SimpleSchema({
game: {
type: String,
label: "Game"
},
console: {
type: String,
label: "Console"
},
players: {
type: Number,
label: "Players"
},
mic: {
type: Boolean,
label: "Mic"
},
note: {
type: String,
label: "Note"
},
gamertag: {
type: String,
label: "Gamertag"
},
createdAt: {
type: Date,
label: "Created At",
autoValue: function(){
return new Date()
},
autoform: {
type: "hidden"
}
}
});
For the first value "game", I need to assign a variable to that.

How to get relationship model in Keystone.js

So I try to get 'Pronouns' model from 'Sentence' model from 'TestGenerator' model. And I have id's, but no model.
TestGenerator Model
var TestGenerator = new keystone.List('TestGenerator', {
map: { name: 'title' },
autokey: { path: 'slug', from: 'title', unique: true }
});
TestGenerator.add({
title: { type: String, required: true },
sentences: { type: Types.Relationship, ref: 'Sentence', many: true },
});
TestGenerator.register();
var Sentence = new keystone.List('Sentence', {
map: { name: 'title' },
autokey: { path: 'slug', from: 'title', unique: true }
});
Sentence Model
Sentence.add({
title: { type: String, required: true },
pronouns: { type: Types.Relationship, ref: 'Pronoun', many: true },
verbs: { type: Types.Relationship, ref: 'Verb', many: true },
});
Sentence.relationship({ ref: 'TestGenerator', path: 'sentences' });
Sentence.register();
Ponoun model
var Pronoun = new keystone.List('Pronoun', {
map: { name: 'english' },
autokey: { path: 'slug', from: 'english', unique: true },
});
Pronoun.add({
english: { type: String },
russian: { type: String }
});
Pronoun.relationship({ ref: 'Sentence', path: 'pronouns' });
Pronoun.register();
And my controller
view.on('init', function (next) {
var q = keystone.list('TestGenerator').model.findOne({
slug: locals.filters.test_genetation,
}).populate('sentences');
q.exec(function (err, result) {
locals.testGenerator = result;
locals.current_sentence = result.sentences[0];
locals.data.englishSentence = locals.current_sentence.pronouns;
console.log(locals.data.englishSentence);
next(err);
});
});
And "locals.data.englishSentence" return
["5739bd696ef7d78d16e9e0e5","573ac7645e3d7d7210f1c4be"]
So how I can fix it? Don't understand.
This is related to mongoose, not Keystone actually. Mongoose doesn't provide deep population, you'll need a separate plugin like e.g. mongoose-deep-populate
Have you tried explicitly including pronouns in the populate() call?
var q = keystone.list('TestGenerator').model.findOne({
slug: locals.filters.test_genetation,
})
.populate('sentences sentences.pronouns')
.exec(function (err, result) {
...
});

Meteor AutoForm: How to update schema values with array of sub-documents?

I am new to Meteor AutoForm. I want to update player docs with country doc. Below is my code. If I add{{> afQuickField name="country"}} in AutoForm it doesn't works. {{> afQuickField name="name"}} alone works fine. How do I add entire country docs (_id,slug,name) in players country field?
JS:
CountrySchema = new SimpleSchema({
_id: {
type: String,
index: true
},
slug: {
type: String,
max: 100,
index: true
},
name: {
type: String,
max: 100
}
});
Player.attachSchema(new SimpleSchema({
name: {
type: String,
label: "Player name",
index: true
},
country: {
type: [CountrySchema],
label: "country",
max: 5,
index: true,
autoform: {
options: function() {
return Country.find().fetch().map(function(object) {
return {
label: object.name,
value: object._id
};
});
}
}
}
}));
HTML:
{{#autoForm id="editplayer" }}
{{> afQuickField name="name"}}
{{> afQuickField name="country"}}
{{/autoForm}}
I added SimpleSchema.debug = true; console log shows SimpleSchema invalid keys for "editplayer" context.
If you want to render country as an array field you could use the afArrayField component:
<template name="editPlayer">
{{#autoForm id="editplayer" collection="Player" type="update" doc=currentPlayer}}
{{> afQuickField name="name"}}
{{> afArrayField name="country"}}
<button type="submit">Submit</button>
{{/autoForm}}
</template>
if (Meteor.isClient) {
AutoForm.debug();
Template.editPlayer.helpers({
currentPlayer: function () {
return Player.findOne();
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
let country = {slug: 'austria', name: 'Austria'};
Country.insert(country);
Player.insert({name: 'Matthias Eckhart', country: [country]});
});
}
Player = new Mongo.Collection("player");
Country = new Mongo.Collection("country");
CountrySchema = new SimpleSchema({
slug: {
type: String,
max: 100,
index: true
},
name: {
type: String,
max: 100
}
});
Player.attachSchema(new SimpleSchema({
name: {
type: String,
label: "Player name",
index: true
},
country: {
type: [CountrySchema],
label: "country",
max: 5,
index: true,
autoform: {
options: function () {
return Country.find().map((object) => ({label: object.name, value: object._id}));
}
}
}
}));
Please note, that I assumed you want to update a player document. Therefore, I set the attribute doc=currentPlayer and specified a player document via the currentPlayer helper function. If you set the data context, for instance via the data function in your Iron Router route, you could use doc=this.
If you want to have a simple select form, your current data structure may require a workaround. The problem is that [CountrySchema] does not expand into proper schema keys. As a result, you need to explicitly specify the full schema and convert the selected options using AutoForm hooks and a Meteor helper function (currentPlayer):
<template name="editPlayer">
{{#autoForm id="editplayer" collection="Player" type="update" doc=currentPlayer}}
{{> afQuickField name="name"}}
{{> afQuickField name="country"}}
<button type="submit">Submit</button>
{{/autoForm}}
</template>
if (Meteor.isClient) {
AutoForm.debug();
Template.editPlayer.helpers({
currentPlayer: function () {
let player = Player.findOne();
if (player) player.country = _.map(player.country, (country) => country._id);
return player;
}
});
var playerUpdateHook = {
before: {
update: function (doc) {
doc['$set'].country = _.map(doc['$set'].country, (countryId) => Country.findOne({_id: countryId}));
return doc;
}
}
};
AutoForm.addHooks('editplayer', playerUpdateHook);
}
if (Meteor.isServer) {
Meteor.startup(function () {
let country = {slug: 'austria', name: 'Austria'};
let countryId = Country.insert(country);
country = Country.findOne({_id: countryId});
Player.insert({name: 'Matthias Eckhart', country: [country]});
});
}
Player = new Mongo.Collection("player");
Country = new Mongo.Collection("country");
CountrySchema = new SimpleSchema({
_id: {
type: String,
index: true
},
slug: {
type: String,
max: 100,
index: true
},
name: {
type: String,
max: 100
}
});
Player.attachSchema(new SimpleSchema({
name: {
type: String,
label: "Player name",
index: true
},
country: {
type: [CountrySchema],
label: "country",
max: 5,
index: true
},
'country.$': {
type: String,
autoform: {
options: function () {
return Country.find().map((object) => ({label: object.name, value: object._id}));
}
}
}
}));

Categories

Resources