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}}
Related
So I have a semantic type collection here to define my type. It has a field arrayValue. The functionality is the new semantic type here can be an array of existing semantic types, either predefined or defined by the user. The problem is that all the semantic types are stored in the collection itself. So is it possible to get the values in collection (something like SemanticTypes.findOne().semanticType) when defined the schema? Here's the code:
collection:
SemanticTypes = new Meteor.Collection('semanticTypes');
Schemas.SemanticTypes = new SimpleSchema({
semanticType: {
type: String,
regEx: /^[a-zA-Z_][a-zA-Z0-9_]*$/,
unique: true
},
baseType:{
type: String,
autoform: {
options: [
{label: "int", value: "int"},
{label: "float", value: "float"},
{label: "string", value: "string"},
{label: "bool", value: "bool"},
{label: "array", value: "array"}
]
}
},
arrayValue: {
type: String,
optional: true,
autoform: {
options:
// I want to get all current semantic types in the collection now
}
}
});
SemanticTypes.attachSchema(Schemas.SemanticTypes);
html:
<template name="addSemanticTypeForm">
{{#autoForm collection="SemanticTypes" id="insertSemanticTypeForm" type="insert"}}
<fieldset>
{{> afQuickField name='semanticType'}}
{{> afQuickField name='baseType' }}
{{#if isArraySelected}}
{{> afQuickField name='arrayValue'}}
{{/if}}
</fieldset>
<button type="submit" class="btn btn-primary">Add</button>
{{/autoForm}}
</template>
js:
Template.addSemanticTypeForm.onCreated(function() {
Session.set("isArraySelected", false);
});
Template.addSemanticTypeForm.helpers({
isArraySelected: function() {
return Session.get("isArraySelected");
}
});
Template.addSemanticTypeForm.events({
'change select[name=baseType]': function(evt) {
if ($(evt.currentTarget).val() == "array"){
Session.set("isArraySelected", true);
}
else {
Session.set("isArraySelected", false);
}
}
});
I actually found a way to do it by defining an options variable in the helper to get all values in the collection with collection.find(), and use {{> afQuickField name="arrayType" options=arrayOptions}} in html. Here's my code:
js:
Template.addSemanticTypeForm.onCreated(function() {
Session.set("isArraySelected", false);
});
Template.addSemanticTypeForm.helpers({
isArraySelected: function() {
return Session.get("isArraySelected");
},
arrayOptions: function(){
var options = [];
SemanticTypes.find().forEach(function(type){
options.push({label: type.semanticType, value: type.semanticType});
});
return options;
}
});
Template.addSemanticTypeForm.events({
'change select[name=baseType]': function(evt) {
if ($(evt.currentTarget).val() == "array"){
Session.set("isArraySelected", true);
}
else {
Session.set("isArraySelected", false);
}
}
});
html:
<template name="addSemanticTypeForm">
{{#autoForm collection="SemanticTypes" id="insertSemanticTypeForm" type="insert"}}
<fieldset>
{{> afQuickField name='semanticType'}}
{{> afQuickField name='baseType' }}
{{#if isArraySelected}}
{{> afQuickField name='arrayValue' options=arrayOptions}}
{{/if}}
</fieldset>
<button type="submit" class="btn btn-primary">Add</button>
{{/autoForm}}
</template>
The autoform is only recording one accept/reject which it applies to all jobOffers. Doesn't doc=this refer to the individual jobOffer when inside an {{#each}} statement.
Path: Schema.js
Schemas.Offers = new SimpleSchema({
offer: {
type: String,
optional: true,
allowedValues: ['Accept', 'Reject'],
autoform: {
type: "select-radio",
options: function () {
return [
{label: "Accept", value: 'Accept' },
{label: "Reject", value: 'Reject' },
];
}
}
}
});
Path: template.html
{{#each jobOffers}}
{{#autoForm collection="Offers" id="offerForm" doc=this type="update" autosave=true}}
{{> afQuickField name="offer" type="select-radio" template="buttonGroup" label=false}}
{{/autoForm}}
{{/each}}
All forms in your loop uses the same id='offerForm' which is what is used to determine the destination.
Fix this by adding a dynamic id to your Autoform.
If jobOffers is a cursor from Mongo, it will have a unique _id you can use to prefix/postfix on your form id with something like id='offerForm{{_id}}'
The solution was to create a helper.
Path: helper.js
Template.Offer.helpers({
jobOffers: function () {
return JobOffers.find({candidateUserId: Meteor.userId()});
},
makeUniqueID: function () {
return this._id;
}
});
Path: template.html
{{#each jobOffers}}
{{#autoForm collection="JobOffers" id=makeUniqueID doc=this type="update"}}
{{> afQuickField name='offer'}}
<button type="submit" class="btn btn-primary submit">Update</button>
{{/autoForm}}
{{/each}}
I'm using autoform with simple schema and collection2 and I've created a schema with subfields. I'm having trouble accessing the subfields in my template. I seem to just get [object object]. The subfields are arrays. Can someone tell me what I'm missing.
Path: template.html
{{#with currentUser}}
{{#with profile}}
{{#each CV}}
{{languages}}
{{/each}}
{{/with}}
{{/with}}
Path: schema.js
Schema.Language = new SimpleSchema({
language: {
type: String,
optional: true
},
proficiency: {
type: String,
optional: true
}
});
Schema.CV = new SimpleSchema({
languages: {
type: [Schema.Language],
optional: true
}
});
Schema.UserProfile = new SimpleSchema({
CV: {
type: Schema.CV,
optional: true,
},
});
Schema.User = new SimpleSchema({
profile: {
type: Schema.UserProfile,
optional: true
}
});
Schema.Language has several properties, which means it's an object. Try this:
{{#with currentUser}}
{{#with profile}}
{{#each CV}}
{{#each languages}}
{{language}}
{{/each}}
{{/each}}
{{/with}}
{{/with}}
You also could replace the #each CV with a #with operator, as CV is not an array in your schema.
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);
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