I'm getting this console message when displaying a group of update forms together. As far as I can tell I've followed the Autoform example correctly. Can anyone tell me what I'm doing wrong?
SimpleSchema.clean: filtered out value that would have affected key "_id", which is not allowed by the schema
Path: form.html
{{#each student}}
{{#autoForm id=makeUniqueID type="update" collection="StudentHistory" doc=this}}
<div class="panel panel-default edit-profile-margin-pannel">
<div class="panel-body">
{{> afQuickField name='class'}}
</div>
</div>
{{/autoForm}}
{{/each}}
Path: form.js
Template.form.helpers({
student: function() {
return StudentHistory.find({});
},
makeUniqueID: function () {
return "update-each-" + this._id;
}
});
Path: Schema.js
StudentHistory = new Mongo.Collection("studentHistory");
StudentHistory.allow({
insert: function(userId, doc) {
return !!userId;
},
update: function(userId, doc) {
return !!userId;
},
remove: function(userId, doc) {
return !!userId;
}
});
var Schemas = {};
Schemas.StudentHistory = new SimpleSchema({
studentUserId: {
type: String,
autoValue: function() {
return this.userId;
},
autoform: {
type: "hidden"
}
},
class: {
type: String,
optional: false
}
});
StudentHistory.attachSchema(Schemas.StudentHistory);
My error was in the template helper. The message disappears when I add the code below.
Template.form.helpers({
student: function() {
return StudentHistory.find({"studentUserId": Meteor.userId()});
}
});
Related
Not sure where I'm going wrong here, please kindly assist.
Please see error below. Thank You
////This is the client side JS////
if (Meteor.isClient) {
Template.NewPerson.helpers({
PersonSchema: function(){
return schema.PersonSchema;
}
});
}
////This is the schema////
Person = new Mongo.Collection('person');
Person.allow({
insert: function(userID, doc){
return !!userID;
}
});
const PersonSchema = new SimpleSchema({
FirstName: {
type: String,
label: "First Name"
},
LastName: {
type: String,
label: "Last Name"
},
IdentityNumber: {
type: Number,
label: "Identity Number"
},
Address: {
type: String,
label: "Address"
},
PhoneNumber: {
type: Number,
label: "Phone Number"
},
User: {
type: String,
label: "User",
autoValue: function(){
return this.userId;
},
autoform: {
type: "hidden",
label: false,
},
},
//createdAt: {
// type: Date,
// label: "Created At",
// autoValue: function(){
// }
// autoForm: {
// type: "hidden"
//},
});
Person.attachSchema(PersonSchema);
Error:
Exception in template helper: TypeError: Cannot read property 'schema' of undefined
////This is the error////
Exception in template helper: TypeError: Cannot read property 'schema' of undefined
at Object.quickFormContext (http://localhost:3000/packages/aldeed_autoform.js?hash=5dbf44ff89f182bd8c2512330e170ef4d5bf9582:6713:34)
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:2994:16
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:1653:16
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:3046:66
at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:3687:12)
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:3045:27
at Object.Spacebars.call (http://localhost:3000/packages/spacebars.js?hash=65db8b6a8e3fca189b416de702967b1cb83d57d5:172:18)
at http://localhost:3000/packages/aldeed_autoform.js?hash=5dbf44ff89f182bd8c2512330e170ef4d5bf9582:6662:23
at wrappedArgFunc (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:2903:14)
at .<anonymous> (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:2616:26)
debug.js:41 Exception in defer callback: TypeError: Cannot read property 'id' of null
at .<anonymous> (http://localhost:3000/packages/aldeed_autoform.js?hash=5dbf44ff89f182bd8c2512330e170ef4d5bf9582:6551:22)
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:1875:20
at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:3687:12)
at http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:1873:29
at Object.Blaze._withCurrentView (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:2214:12)
at viewAutorun (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:1872:18)
at Tracker.Computation._compute (http://localhost:3000/packages/tracker.js?hash=f525263111eb9d90f4ce1ad064f97aca4a6c1b07:339:36)
at new Tracker.Computation (http://localhost:3000/packages/tracker.js?hash=f525263111eb9d90f4ce1ad064f97aca4a6c1b07:229:10)
at Object.Tracker.autorun (http://localhost:3000/packages/tracker.js?hash=f525263111eb9d90f4ce1ad064f97aca4a6c1b07:604:11)
at Blaze.View.autorun (http://localhost:3000/packages/blaze.js?hash=ef41aed769a8945fc99ac4954e8c9ec157a88cea:1885:22)
////This is the client side HTML////
<template name="NewPerson">
<div class="new-person-container">
{{> quickForm collection=Person id="insertPersonForm" type="insert" class="new-person-form"}}
</div>
</template>
You need to quote the collection name when defining the quickForm:
<template name="NewPerson">
<div class="new-person-container">
{{> quickForm collection="Person" id="insertPersonForm" type="insert" class="new-person-form"}}
</div>
</template>
In your helper file you also need:
import { Meteor } from 'meteor/meteor'
and possibly also:
import { Person } from 'pathToYourSchemaFile'
Person = new Mongo.Collection('person');
Person.allow({
insert: function(userID, doc){
return !!userID;
}
});
Person.attachSchema(new SimpleSchema({
FirstName: {
type: String,
label: "First Name"
},
LastName: {
type: String,
label: "Last Name"
},
IdentityNumber: {
type: Number,
label: "Identity Number"
},
Address: {
type: String,
label: "Address"
},
PhoneNumber: {
type: Number,
label: "Phone Number"
},
User: {
type: String,
label: "User"
},
}));
<template name="NewPerson">
<div class="new-person-container">
{{> quickForm collection=Person id="insertPersonForm" type="insert" class="new-person-form"}}
</div>
</template>
You don't need to pass schema into quick form once you attach it to collection.
It will determine what kind of data to populate based on collection schema.
Meteor.subscribe('person');
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
Template.Person.onCreated(function(){
this.editMode = new ReactiveVar(false);
// this.editMode = new ReactiveVar();
// this.editMode.set(false);
});
Template.Person.helpers({
updatePersonId: function() {
return this._id;
},
editMode: function() {
return Template.instance().editMode.get();
}
});
Template.Person.events({
'click .toggle-menu': function() {
Meteor.call('toggleMenuItem', this._id, this.inMenu);
},
'click .fa-trash' : function() {
Meteor.call('deletePerson', this._id);
},
'click .fa-pencil' : function(event, template) {
template.editMode.set(!template.editMode.get());
}
});
I want to insert a new document into db using autoform. Autoform hook calls a meteor method on server to insert the document.
I have this in template...
{{#autoForm collection="Reports" id="addReport" type="insert"}}
<div class="row">
<div class="col s6">
{{> afQuickField name='hours'}}
</div>
</div>
<button class="btn waves-effect waves-light modal-action modal-close"><i class="material-icons">save</i></button>
{{/autoForm}}
Then...
AutoForm.hooks({
addReport: {
onSubmit: function(insertDoc) {
Meteor.call('addReport', insertDoc, function(error, result) {
if (error) alert(error.reason);
});
return false;
}
}
});
then the method on server...
Meteor.methods({
addReport: function(insertDoc) {
var report = _.extend(insertDoc, {
userId: Meteor.userId(),
});
return Reports.insert(report);
}
});
I have a createdAt and updatedAt fields in collection, but they all have autoValue thus, I believe no need to do insertion from client or in the meteor method.
So collection with schema looks like this:
Reports = new Meteor.Collection('reports');
Reports.attachSchema(new SimpleSchema({
hours: {
type: Number,
label: "Number of hours",
decimal: true
},
createdAt: {
type: Date,
label: "Created Date",
autoValue: function() {
if (this.isInsert) {
return new Date;
} else {
this.unset();
}
},
denyUpdate: true
},
updatedAt: {
type: Date,
autoValue: function() {
if (this.isUpdate) {
return new Date()
}
},
denyInsert: true,
optional: true
},
"userId": {
type: String,
autoform: {
type: "hidden",
}
},
}));
When i run meteor, form displays, but submit does nothing. No visual cue as to if any error. No error message in both client and server console.
what am I doing wrong or missing?
Since #Cristo GQ got it right, I just want to make sure the answer is clear enough for future visitors of this thread
The onSubmit hook will be used only for autoForms with type='normal' or without any type= at all
On another note, the before.insert hook is just for type='insert' And there is no before.normal hook
This mean that when using the onSubmit hook, we have to do any "before work" (like adding currentUser to the doc) inside the onSubmit itself.
aldeed/meteor-autoform documentation:
// Called when form does not have a `type` attribute
onSubmit: function(insertDoc, updateDoc, currentDoc) {
Meteor.call()...
}
I'm following discovermeteor book, and I'm trying to use some methods of the book, but using the meteor-autoform package.
post_submit.html
<template name="postSubmit">
{{#autoForm collection="Posts" id="insertPost"}} <-- no type
<div class="form-group">
<div class="controls">
{{> afQuickField name='title' class='title form-control'}}
</div>
</div>
<div class="form-group">
<div class="controls">
{{> afQuickField name='description' class='description form-control'}}
</div>
</div>
<input id="send" type="submit" value="Send" class="btn btn-primary"/>
{{/autoForm}}
</template>
post_submit.js
var postSubmitHook = {
onSubmit: function(insertDoc){
Meteor.call('postInsert', insertDoc, function(error, result) {
if (error){
Bert.alert(error.reason, 'danger', 'growl-top-right');
$('#send').removeAttr('disabled');
return;
}
Router.go('postPage', {_id: result._id});
});
return false;
}
};
AutoForm.addHooks('insertPost', postSubmitHook);
New to MeteorJS. I started making a novel Clan/Samurai app to see if I could understand how mongo/meteor and Autoforms handle relationships. I'm trying to make clans and samurai relate to each other so that each Samurai has a specific clan.
I'm attempting to insert the clan data into the Samurai identity. I seem to not be able to.
I've read the following and still seem generally confused on how to implement this. I've tried before, onsuccess, onsubmit hooks. I've attempted to set the schema up so that it works. I mostly get AutoForm undefined or Schema undefined...tons of errors it seems. I've read that it should be client.
I can console log and get it to render but I can't add the new items to the collection.
Random Github made for viewing pleasure
https://github.com/qtheninja/SamuraiAttack
https://github.com/aldeed/meteor-collection2/issues/31
How to add a relationship or reference with AutoForm in Meteor?
Meteor Autoform package with collection2 does not submit the form
//lib/collections/clans.js
Clans = new Mongo.Collection('clans');
Clans.attachSchema(new SimpleSchema({
name: {
type: String,
label: "Clan Name",
max: 100
}
}));
if (Meteor.isServer) {
Clans.allow({
insert: function (userId, doc) {
return true;
},
update: function (userId, doc, fieldNames, modifier) {
return true;
},
remove: function (userId, doc) {
return true;
}
});
}
//lib/collections/samurais.js
Samurais = new Mongo.Collection('samurais');
Samurais.attachSchema(new SimpleSchema({
title: {
type: String,
label: "Title",
max: 100
},
description: {
type: String,
label: "Description",
optional: true
},
clan: {
type: Clans
}
}));
if (Meteor.isServer) {
Samurais.allow({
insert: function (userId, doc) {
return true;
},
update: function (userId, doc, fieldNames, modifier) {
return true;
},
remove: function (userId, doc) {
return true;
}
});
}
//client/template/clans/createClan.html
<template name="CreateClan">
<h1>Create New Clan</h1>
{{> quickForm
collection="Clans"
id="insertClanForm"
type="insert"
buttonContent="Create"
}}
<div>
{{> ListClans }}
</div>
</template>
//client/main.js
AutoForm.addHooks('insertSamuraiForm', {
before: {
insert: function(doc, template) {
//modify the document here
doc.clanid= 45;
doc.dance ="start again";
console.log("running after hook");
return true;
}
}
});
AutoForm.hooks({
insertSamuraiForm: {
before: {
insert: function(doc, template) {
//modify the document here
doc.projectid= "random";
doc.dance ="start again";
console.log('this is asecond form');
}
}
}
});
I was able to resolve this issue by doing the following.
Return on object using 'before' hook
Router.current().params._id
a. I was using iron router and in my url was clans/_id/samurai/new
added 'dance' and 'clanid' as apart of the simpleschema. I had neglected to include them as apart of the schema so I was getting the console.log to work but not the data to be apart of the object.
//client/lib/main.js (alterations)
before: {
insert: function(doc, template) {
//modify the document here
doc.clanid= Router.current().params._id;
doc.dance ="start again";
console.log("running after hook");
return doc;
}
}
//lib/collections/samurais.js
Samurais = new Mongo.Collection('samurais');
Samurais.attachSchema(new SimpleSchema({
title: {
type: String,
label: "Title",
max: 100
},
description: {
type: String,
label: "Description",
optional: true
},
clanid: {
type: String,
label: "ignore this",
optional: true
},
dance: {
type: String,
optional: true
}
}));
if (Meteor.isServer) {
Samurais.allow({
insert: function (userId, doc) {
return true;
},
update: function (userId, doc, fieldNames, modifier) {
return true;
},
remove: function (userId, doc) {
return true;
}
});
}
I'm making a simple Meteor app that can redirect to a page when user click a link.
On 'redirect' template, I try get the value of property 'url' from the template instance. But I only get right value at the first time I click the link. When I press F5 to refresh 'redirect' page, I keep getting this error message:
Exception from Tracker afterFlush function: Cannot read property 'url' of null
TypeError: Cannot read property 'url' of null
at Template.redirect.rendered (http://localhost:3000/client/redirect.js?abbe5acdbab2c487f7aa42f0d68cf612f472683b:2:17)
at null.
This is where debug.js points to: (line 2)
if (allArgumentsOfTypeString)
console.log.apply(console, [Array.prototype.join.call(arguments, " ")]);
else
console.log.apply(console, arguments);
} else if (typeof Function.prototype.bind === "function") {
// IE9
var log = Function.prototype.bind.call(console.log, console);
log.apply(console, arguments);
} else {
// IE8
Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
}
Can you tell me why I can't read the value of 'url' property from template data context in template rendered callback?
This is my code (for more details, you can visit my repo):
HTML:
<template name="layout">
{{>yield}}
</template>
<template name="home">
<div id="input">
<input type="text" id="url">
<input type="text" id="description">
<button id="add">Add</button>
</div>
<div id="output">
{{#each urls}}
{{>urlItem}}
{{/each}}
</div>
</template>
<template name="redirect">
<h3>Redirecting to new...{{url}}</h3>
</template>
<template name="urlItem">
<p><a href="{{pathFor 'redirect'}}">
<strong>{{url}}: </strong>
</a>{{des}}</p>
</template>
home.js
Template.home.helpers({
urls: function(){
return UrlCollection.find();
}
});
Template.home.events({
'click #add': function() {
var urlItem = {
url: $('#url').val(),
des: $('#description').val()
};
Meteor.call('urlInsert', urlItem);
}
});
redirect.js
Template.redirect.rendered = function() {
if ( this.data.url ) {
console.log('New location: '+ this.data.url);
} else {
console.log('No where');
}
}
Template.redirect.helpers({
url: function() {
return this.url;
}
});
router.js
Router.configure({
layoutTemplate: 'layout'
})
Router.route('/', {
name: 'home',
waitOn: function() {
Meteor.subscribe('getUrl');
}
});
Router.route('/redirect/:_id', {
name: 'redirect',
waitOn: function() {
Meteor.subscribe('getUrl', this.params._id);
},
data: function() {
return UrlCollection.findOne({_id: this.params._id});
}
});
publication.js
Meteor.publish('getUrl', function(_id) {
if ( _id ) {
return UrlCollection.find({_id: _id});
} else {
return UrlCollection.find();
}
});
Add this
Router.route('/redirect/:_id', {
name: 'redirect',
waitOn: function() {
Meteor.subscribe('getUrl', this.params._id);
},
data: function() {
if(this.ready()){
return UrlCollection.findOne({_id: this.params._id});
}else{
console.log("Not yet");
}
}
});
Tell me if works.
With help from my colleague, I can solve the problem.
My problem comes from wrong Meteor.subscribe syntax. In my code, I forget "return" in waitOn function. This will make Meteor do not know when the data is fully loaded.
Here is the right syntax:
waitOn: function() {
return Meteor.subscribe('getUrl', this.params._id);
}
I am building part of an admin system in Meteor that lets admins add/edit other admins. I am using Meteor Accounts and Autoform, but I can't figure out how to handle it so the users are validated with Autoform and saved properly. From what i've found it looks like I need to use the Accounts.createUser method and make the form a type="method" or something, but I'm not sure how to handle that or if that is even the correct way.
Here is my code right now:
Schema:
Schema = {};
Schema.UserProfile = new SimpleSchema({
name: {
type: String,
label: "Name"
}
});
Schema.User = new SimpleSchema({
email: {
type: String,
regEx: SimpleSchema.RegEx.Email
},
password: {
type: String,
label: "Password",
min: 6
},
passwordConfirmation: {
type: String,
min: 6,
label: "Password Confirmation",
custom: function() {
if (this.value !== this.field('password').value) {
return "passwordMissmatch";
}
}
},
createdAt: {
type: Date,
autoValue: function() {
if (this.isInsert) {
return new Date;
} else if (this.isUpsert) {
return {$setOnInsert: new Date};
} else {
this.unset();
}
}
},
profile: {
type: Schema.UserProfile
},
services: {
type: Object,
optional: true,
blackbox: false
}
});
Meteor.users.attachSchema(Schema.User);
Routes:
Router.route('/admin/admins', {
controller: 'AdminController',
name: 'adminAdmins',
title: 'Admins',
parent: 'adminHome',
});
Router.route('/admin/admins/new', {
controller: 'AdminController',
name: 'adminAdminNew',
title: 'New Admin',
parent: 'adminAdmins',
});
Router.route('/admin/admins/:_id/edit', {
controller: 'AdminController',
name: 'adminAdminEdit',
title: 'Edit Admin',
parent: 'adminAdmins',
data: function() {
return Meteor.users.findOne(this.params._id);
}
});
Admin Form:
{{#autoForm collection="Meteor.users" doc=this id="adminAdminForm" type=formType}}
{{> afQuickField name='profile.name'}}
{{> afQuickField name='email'}}
{{> afQuickField name='password'}}
{{> afQuickField name='passwordConfirmation'}}
<button type="submit" class="btn btn-block btn-secondary">Save Changes</button>
{{/autoForm}}
You should add Hooks to be able to modify the collection
Something that should look like this
AutoForm.hooks({
adminAdminForm: {
onSubmit: function (doc) {
schemas.User.clean(doc);
this.done();
return false;
},
onSuccess:function(operation, result, template){
Router.go('users.show',{'username':template.data.doc.username});
},
onError: function(operation, error, template) {
console.log(operation,error)
}
}
});
You can find more details on the dedicated documentation https://github.com/aldeed/meteor-autoform#callbackshooks