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
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'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()});
}
});
I've changed my schema to include sub-schemas. I want to group relevant data together and make it easier to manage. Unfortanly this has broken my registration process. How do I make the autoform insert firstName into the sub-schema. Any thoughts?
Path: at_config.js
AccountsTemplates.addFields([
{
_id: "details.firstName",
type: 'text',
displayName: "First name",
required: true,
minLength: 1,
maxLength: 37
}
]);
Path: Schema.js
AccountsTemplates.configure({
Schema.UserDetails = new SimpleSchema({
firstName: {
type: String,
optional: false
}
});
Schema.UserProfile = new SimpleSchema({
details: {
type: Schema.UserDetails,
optional: true
},
});
Schema.User = new SimpleSchema({
profile: {
type: Schema.UserProfile,
optional: true
}
});
Meteor.users.attachSchema(Schema.User);
Path: startup.js
Accounts.onCreateUser(function (options, user) {
if (options.profile && options.profile.roles) {
//include the user profile
Roles.setRolesOnUserObj(user, options.profile.roles);
}
if (options.profile) {
// include the user profile
user.profile = options.profile;
}
return user;
});
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 try create user profile page with autoform, but autorofm tell me "Error: AutoForm: You must specify a collection when form type is insert."
I have only one way through the methods?
Please help me to solve the problem.
Helper
Template.accountForm.helpers({
userSchema: function () {
return Schema.User;
}
});
Template
<template name="accountForm">
<div class="panel-body">
{{#autoForm schema=userSchema collection=Users id="accountForm" type="insert"}}
<fieldset>
{{> afObjectField name='profile'}}
</fieldset>
<button type="submit" class="btn btn-primary">Insert</button>
{{/autoForm}}
</div>
</template>
Schema
Schema = {};
Schema.UserProfile = new SimpleSchema({
lastname: {
type: String
}
});
Schema.User = new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id
},
email: {
type: String,
regEx: SimpleSchema.RegEx.Email
},
createdAt: {
type: Date
},
profile: {
type: Schema.UserProfile,
},
services: {
type: Object,
optional: true,
blackbox: false
}
});
Meteor.users.attachSchema(Schema.User);
You don't need the helper function, just use the Meteor.users object.
{{#autoForm collection='Meteor.users' doc=currentUser type='update' id='accountForm'}}
{{> afQuickField name='profile'}}
<button type='submit' class="btn btn-primary">Save profile</button>
{{/autoForm}}