im doing the "Intermediate Meteor Tutorial #8 - Insert Permissions, Publishing & Meteor Toys" by LevelUpTuts and my problem is that i cant submit the form i checked the code 5 times but in my opinion everything is right im running meteor 1.4 here is my code
my Recipes.js file
Recipes = new Meteor.Collection('recipes');
Recipes.allow({
insert: function(userId, doc) {
return !!userId;
}
});
RecipeSchema = new SimpleSchema ({
name: {
type: String,
label: "Name"
},
desc: {
type: String,
label: "Description"
},
author: {
type: String,
label: "Author",
autoValue: function() {
return this.userID
},
autoform: {
type: "hidden"
},
},
createdAt: {
type: Date,
label: "CreatedAt",
autoValue: function() {
return new Date()
},
autoform: {
type: "hidden"
},
},
});
Recipes.attachSchema( RecipeSchema);
my recipes.js
Meteor.subscribe('recipes');
my NewRecipe.js
<template name="NewRecipe">
<div class="new-recipe-container">
{{> quickForm collection="Recipes" id="insertRecipeForm" type="insert" class="new-recipe-form"}}
</div>
</template>
and the publis.js file
Meteor.publish('recipes', function(){
return Recipes.find({author: this.userId});
});
Please help me i dont know what i am doing wrong
i don't have the answer for you (at least not yet), but i'm posting this as an answer so i can provide some formatted code.
you posted some code under NewRecipe.js, but i assume that view code is in NewRecipe.html. Try 2 things:
first, put this code in NewRecipe.js onCreated():
SimpleSchema.debug = true;
AutoForm.addHooks(null, {
onError: function(name, error, template) {
console.log(name + " error:", error);
}
});
that will enable some debugging for the quickform.
second, in the schema definition, comment out the Recipes.allow() block to see if that's what's blocking saving your data.
then report back on how that goes.
Related
Well, I have a user model that needs to implement customToJSON and make the removal of the password for the object to be returned json.
When I put the "responseType" in "exits" as "json" everything happens fine, and the password is taken out of the response. However, the responseType: "json" will be deprecated according to the message in the terminal that sends the responseType empty, however the customToJSON is not called. Can anyone help me understand this?
this is the model code:
[...]
attributes: {
name: {
type: 'string',
required: true,
},
email: {
type: 'string',
required: true,
},
password: {
type: 'string',
minLength: 6,
required: true,
},
},
customToJSON: function() {
return _.omit(this, ['password']);
},
[...]
this is the action code:
module.exports = {
friedlyName: 'Users List',
description: 'User list -> all users',
exits: {
success: {
}
},
fn: async (inputs, exits) => {
var users = await User.find();
return exits.success(users);
}
}
this is the message if you put the "responseType: 'json'":
The json response type will be deprecated in an upcoming release. Please use `` (standard) instead (i.e. remove responseType from the success exit.)
I defined custom responses inside api/responses folder.
So, for example... for 200 OK response create api/responses/ok.js
and then inside action2 controller method add this to exits:
exits: {
success: {
description: 'Returns ok response from api/responses/ok.js',
responseType: 'ok'
}
}, ...
Example of my simple api/responses/ok.js
module.exports = function ok(data) {
return this.res.status(200).json(data);
};
You can create responses for each status/exit you need and later on it's easy to maintain exits... I have responses for: badRequest, serverError, forbidden, notFound and unauthorized
I am trying to insert a document into my meteor collection with an autoform made from my mongo schema, yet when I press the submit button it is giving me a "method not found [404]" error in the dev console. I believe it is coming from this code:
GameList.allow({
insert: function(userId, doc){
return !!userId;
}
});
which allows people to add documents to the database if they are logged in as a user. Without this code I will receive a "not authorized [403]" error, because I took out the insecure package from my meteor app. Any idea on what is causing this method not found error?
Autoform code:
{{> quickForm collection="GameList" id="insertGameForm" type="insert" class="newGameForm"}}
Schema for autoform:
GameListSchema = new SimpleSchema({
title: {
type: String,
label: "Title"
},
platform: {
type: String,
label: "Platform"
},
category: {
type: String,
label: "Category"
},
gameRank: {
type: String,
label: "GameRank"
},
auth: {
type: String,
label: "Author",
autoValue: function(){
return this.userId
},
autoform: {
type: "hidden"
}
}
});
GameList.attachSchema(GameListSchema);
I believe this is happening because your allow/deny rules are supposed to run on the server according to the Meteor documentation. Try putting them on server-side code and running this again.
I have an insert form which is created using autoform, collection2 and simple schema. The createdBy field is populated with the userId using autovalue. The form worked when using meteor.allow() for the insert but I wanted to replace the allow with a method so that I can do some validating of user roles ie make sure the user has admin rights. But now I get an error that the createdBy field is empty.
The error in dev tools is:
error: 400, reason: "Created by is required", details: undefined,
message: "Created by is required [400]", errorType: "Meteor.Error"}
Courses = new Mongo.Collection('Courses');
courseSchema = new SimpleSchema({
title: {
type: String,
label: "Course Title"
},
description: {
type: String,
label: "Description"
},
createdAt: {
type: Date,
autoValue: function(){
return new Date();
},
autoform:{
type: 'hidden'
}
},
startDate:{
type: String,
label: "Start Date"
},
sessions: {
type: String,
label: "No. of sessions"
},
duration: {
type: String,
label: "Duration of the course"
},
price: {
type: String,
label: "Course Price"
},
createdBy:{
type: String,
autoValue:function(){
return this.userId;
},
autoform:{
type:'hidden'
}
}
});
Courses.attachSchema(courseSchema);
The method (which is available on the client and the server):
Meteor.methods({
addCourse: function(course){
Courses.insert(course);
}
});
And the template where the form is generated:
<template name="adminIndex">
<h1>Available Courses</h1>
{{> courseList }}
<button type="button" class="btn btn-success btn-block">Create New Course</button>
<h3>Create New Course</h3>
{{>quickForm id="InsertCourseForm" collection="Courses" type="method" meteormethod="addCourse"}}
</template>
You need to clean the object by calling Courses.simpleSchema().clean(course); in the server method in order to add auto and default values securely. Also, please note that this.userId in your autoValue function is null for server-initiated actions, so you probably want to replace it with Meteor.userId().
In addition, you must perform your own validation by calling check(value, pattern) in the Meteor method, because client side validation can be bypassed.
For example:
if (Meteor.isServer) {
Meteor.methods({
addCourse: function(course) {
Courses.simpleSchema().clean(course);
check(course, Courses.simpleSchema());
Courses.insert(course);
}
});
}
So this worked but I haven't seen it used in any other examples so I have a bad feeling, but until I can find out more it will have to do:
createdBy:{
type: String,
autoValue:function(){
if(Meteor.isClient){
return this.userId;
}else if(Meteor.isServer){
return Meteor.userId();
}
},
I have the following Schema:
Dates.attachSchema(new SimpleSchema({
description: {
type: String,
label: "Description",
max: 50
},
start: {
type: Date,
autoform: {
afFieldInput: {
type: "bootstrap-datepicker"
}
}
},
end: {
type: Date,
autoform: {
afFieldInput: {
type: "bootstrap-datepicker"
}
}
}
}));
How can I validate that the end date is not before start? I am using MomentJS to handle date types, however my main problem is how I can access other attributes in the custom function.
For instance:
end: {
type: Date,
autoform: {
afFieldInput: {
type: "bootstrap-datepicker"
}
},
custom: function() {
if (moment(this.value).isBefore(start)) return "badDate";
}
}
How can I access start?
Furthermore, how can I validate if the start + end date combination is unique, meaning there is no document saved in my database which has the exact same start and end date?
For the inter-field communication, you can do:
end: {
type: Date,
autoform: {
afFieldInput: {
type: "bootstrap-datepicker"
}
},
custom: function() {
// get a reference to the fields
var start = this.field('start');
var end = this;
// Make sure the fields are set so that .value is not undefined
if (start.isSet && end.isSet) {
if (moment(end.value).isBefore(start.value)) return "badDate";
}
}
}
You should of course declare the badDate error first
SimpleSchema.messages({
badDate: 'End date must be after the start date.',
notDateCombinationUnique: 'The start/end date combination must be unique'
})
Regarding the uniqueness, first of all simple schema itself does not provide uniqueness check. You should add aldeed:collection2 for that.
Furthermore, collection2 is capable of checking only a single field uniqueness. To accomplish compound indexes, you should use the ensureIndex syntax
Dates._ensureIndex( { start: 1, end: 1 }, { unique: true } )
Even after this, you will not be able to see the error from this compound index on your form because autoform needs to be aware that such error is existing.
AutoForm.hooks({
NewDatesForm: { // Use whatever name you have given your form
before: {
method: function(doc) {
var form = this;
// clear the error that gets added on the previous error so the form can proceed the second time
form.removeStickyValidationError('start');
return doc;
}
},
onSuccess: function(operation, result, template) {
if (result) {
// do whatever you want if the form submission is successful;
}
},
onError: function(operation, error) {
var form = this;
if (error) {
if (error.reason && error.reason.indexOf('duplicate key error')) {
// We add this error to the first field so it shows up there
form.addStickyValidationError('start', 'notDateCombinationUnique'); // of course you have added this message to your definition earlier on
AutoForm.validateField(form.formId, 'start');
}
}
}
}
});
How do you add a property to an entity dynamically? I've been looking, but haven't found anything.
For example, I have this model definition (I'm using the WebSQL provider):
$data.Entity.extend('$db.Types.Person', {
id: { type: 'int', key: true, computed: true },
name: { type: 'string' }
});
$data.EntityContext.extend('$db.Types.DBContext', {
Persons: { type: $data.EntitySet, elementType: $db.Types.Person},
});
At some point I need to extend my model with new properties. Initially I don't know these properties' names.
The syntax is very simple for this, but the background info is more important, please read the whole answer before you reuse the snippet.
The YourType can be extended with new fields using the YourType.addMember() function. See this example snippet:
$data.Entity.extend('Product', {
id: { type: 'int', key: true, computed: true },
Name: { type: 'string' }
});
$data.EntityContext.extend('Northwind', {
Products: { type: $data.EntitySet, elementType: Product},
});
Product.addMember('Description', {
type:'string',
key: false,
computed: false,
required: false
});
var context = new Northwind({provider: 'webSql', databaseName: 'Northwind'});
context.onReady(function() {
var product1 = new Product({ Name: 'Beer', Description: 'tasty'});
context.Products.add(product1);
context.saveChanges(function(result) {
//check the content of WebSQL DB
console.log(product1);
});
});
You can user the addMember() only before creating an instance of the context.
Important info:
There is no data migration/merge by in the library, and the default behavior on schema modification for webSql is to drop&re-create the DB. As IndexedDB isn't bound to a schema, the existing records won't be dropped. Make a try by running this code and adding more fields, here is a working JSFiddle.
The real solution is to use Schema Evolution module of JayData Pro to manage the changes in your data model.