I've installed lukemadera:autoform-googleplace package and followed the usage instructions. When I run the application the address field doesn't auto populate as I type. I get an error in console (Exception in template helper: ReferenceError: EJSON is not defined) can someone please tell me what I'm missing.
Path: Layout.html
<head>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
</head>
Path: Schema.js
Schema.Address = new SimpleSchema({
fullAddress: {
type: String
},
lat: {
type: Number,
decimal: true
},
lng: {
type: Number,
decimal: true
},
geometry: {
type: Object,
blackbox: true
},
placeId: {
type: String
},
street: {
type: String,
max: 100
},
city: {
type: String,
max: 50
},
state: {
type: String,
regEx: /^A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY]$/
},
zip: {
type: String,
regEx: /^[0-9]{5}$/
},
country: {
type: String
}
});
Schema.UserProfile = new SimpleSchema({
address: {
type: Schema.Address,
optional: true
}
});
Path: personalDetails.js
<template name="personalDetails">
{{#autoForm collection="Meteor.users" id="candidateProfile" doc=currentUser type="update"}}
{{> afQuickField name="profile.address" type="googleplace" opts=optsGoogleplace}}
{{/autoForm}}
</template>
Path: personalDetails.js
Template.personalDetails.helpers({
optsGoogleplace: function() {
return {
// type: 'googleUI',
// stopTimeoutOnKeyup: false,
// googleOptions: {
// componentRestrictions: { country:'us' }
// }
}
}
});
FYI, just in case someone else gets this error, you need to install ejson.
Related
I am attempting nest an each statement to handle the two objects that are available within my view. There is a relationship between the two objects with the userId on the card as the connection to the userId on the user table, which might be how this could work. I figure that I might have to end up registering a helper to have this work, but I'm not sure where to start. I attempted to bypass this process with the following handlebars syntax, but I get TypeError: inverse is not a function:
{{#each this.fullNameSlug ../user.fullNameSlug}}
<h5>{{this.fullNameSlug}}</h5>
{{/each}}
Here is the full view:
{{#each card}}
<div class="row">
<div class="card col-md-6 col-md-offset-3">
<div class="card-date">
<p class="card-date">{{this.cardDateSlug}}</p>
</div>
<div class="card-header">
<h3 class="card-title">{{this.title}}</h3>
{{#each this.fullNameSlug ../user.fullNameSlug}}
<h5>{{this.fullNameSlug}}</h5>
{{/each}}
</div>
<div class="card-body">
{{/each}}
Here is the route with the two objects (card, user) that are accessible in the view:
/*==== / ====*/
appRoutes.route('/')
.get(function(req, res){
models.Card.findAll({
order: 'annotationDate DESC',
include: [{
model: models.User,
where: { organizationId: req.user.organizationId },
attributes: ['organizationId', 'userId', 'fullNameSlug']
}],
limit: limitAmount.limit
}).then(function(annotation){
res.render('pages/app/activity-feed.hbs',{
card: card,
user: req.user
});
});
})
Card object:
module.exports = function(sequelize, DataTypes) {
var path = require('path');
var moment = require('moment');
var Card = sequelize.define('card', {
cardId: {
type: DataTypes.INTEGER,
field: 'card_id',
autoIncrement: true,
primaryKey: true
},
cardDate: {
type: DataTypes.DATE,
field: 'card_date',
isDate: true
},
reportLink: {
type: DataTypes.TEXT,
field: 'report_link'
},
fileAttachment: {
type: DataTypes.STRING,
field: 'file_attachment'
},
userId: {
type: DataTypes.INTEGER,
field: 'user_id'
},
discoverySourceId: {
type: DataTypes.INTEGER,
field: 'discovery_source_id'
}
},
{
freezeTableName: true,
getterMethods: {
cardDateSlug: function(){
var date = new Date(this.getDataValue('annotationDate'));
var momentDate = moment(date).utc().format("MM/DD/YYYY");
return momentDate;
}
},
classMethods: {
associate: function(db) {
Card.belongsTo(db.User, {foreignKey: 'user_id'}),
}
}
});
return Card;
}
User object:
var bcrypt = require('bcrypt-nodejs');
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('user', {
userId: {
type: DataTypes.INTEGER,
field:'user_id',
autoIncrement: true,
primaryKey: true
},
firstName: {
type: DataTypes.STRING,
field: 'first_name'
},
lastName: {
type: DataTypes.STRING,
field: 'last_name'
},
email: {
type: DataTypes.STRING,
isEmail: true,
unique: true,
set: function(val) {
this.setDataValue('email', val.toLowerCase());
}
},
password: DataTypes.STRING,
organizationId: {
type: DataTypes.INTEGER,
field: 'organization_id',
allowNull: true
},
authenticationToken: {
type: DataTypes.STRING,
field: 'authentication_token'
},
resetPasswordToken: {
type: DataTypes.STRING,
field: 'reset_password_token'
},
resetPasswordExpires: {
type: DataTypes.DATE,
field: 'reset_password_expires'
}
}, {
freezeTableName: true,
getterMethods: {
fullNameSlug: function(){
var fullName = this.getDataValue('firstName') + ' ' + this.getDataValue('lastName');
return fullName;
}
},
classMethods: {
associate: function(db) {
User.belongsToMany(db.Organization, { through: 'member', foreignKey: 'user_id'})
},
generateHash: function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
},
},
instanceMethods: {
validPassword: function(password) {
return bcrypt.compareSync(password, this.password);
},
},
});
return User;
}
I'm currently using lukemadera:autoform-googleplace to save the users address. When the user saves their address it only saves the fullAddress field in the schema. I thought it broke the address up into its parts; street, state, zip etc. That way you could publish the address parts individually if required. I would like to be able to publish just the state in certain circumstances but I'm not sure how to do that since all I have is a fullAddress field string. Let me know if you need more clarification.
Path: address.js
Template.address.helpers({
optsGoogleplace: function() {
return {
// type: 'googleUI',
// stopTimeoutOnKeyup: false,
googleOptions: {
componentRestrictions: { country:'au' }
}
}
},
});
Path: address.html
{{#autoForm collection="Meteor.users" id="user" doc=currentUser type="update"}}
{{> afQuickField name="profile.address" type="googleplace" opts=optsGoogleplace class="form-control"}}
{{autoForm}}
Path: Schema.js
Schema.Address = new SimpleSchema({
fullAddress: {
type: String
},
lat: {
type: Number,
decimal: true
},
lng: {
type: Number,
decimal: true
},
geometry: {
type: Object,
blackbox: true
},
placeId: {
type: String
},
street: {
type: String,
max: 100
},
city: {
type: String,
max: 50
},
state: {
type: String,
regEx: /^A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY]$/
},
zip: {
type: String,
regEx: /^[0-9]{5}$/
},
country: {
type: String
}
});
If you have it set up correctly, something like this should work:
Schemas = {};
Schemas.Address = new SimpleSchema({
fullAddress: {
type: String
},
lat: {
type: Number,
decimal: true
},
lng: {
type: Number,
decimal: true
},
geometry: {
type: Object,
blackbox: true
},
placeId: {
type: String
},
street: {
type: String,
max: 100
},
city: {
type: String,
max: 50
},
state: {
type: String,
},
zip: {
type: String,
},
country: {
type: String
},
});
Schemas.MainSchema = new SimpleSchema({
address: {
type: Schemas.Address,
optional: true
}
});
MainSchema = new Mongo.Collection("MainSchema");
MainSchema.attachSchema(Schemas.MainSchema);
MainSchema.allow({
insert: function () { return true; },
update: function () { return true; },
remove: function () { return true; }
});
Maybe check these out:
https://github.com/lukemadera/meteor-autoform-googleplace/issues/24
https://github.com/lukemadera/meteor-autoform-googleplace/issues/25
http://www.curtismlarson.com/blog/2015/12/11/meteor-location-search-engine-mongodb-google-maps/
My only other guess is something is wrong with you google options helper. I'm not using that right now and the above setup works for me.
I'm new to Meteor and programming, if this doesn't make sense or you need more info please let me know.
I'm loading a profile page of another user. So I have 2 userIds; this.userId and the other users Id. I want to use autoValue to save both userIds when an action is taken. I can't figure out how to set the other users id even though I can display it on the html page.
Path: schema.js
Schemas.class = new SimpleSchema({
Title: {
type: String,
optional: true
},
teacherProfile: {
type: String,
optional: true,
autoValue: function() {
return this.userId
},
autoform: {
type: "hidden"
}
},
studentProfileId: {
type: String,
optional: true,
type: String,
autoform: {
defaultValue: "studentProfileId",
type: "hidden"
}
}
});
Path: profile.js
Template.teacherProfile.helpers({
studentProfile: ()=> {
var id = FlowRouter.getParam('id');
return Meteor.users.findOne({_id: id});
}
});
This is my solution it seems to work. Thanks to everyone that helped.
Path: schema.js
Schemas.class = new SimpleSchema({
Title: {
type: String,
optional: true
},
teacherProfile: {
type: String,
optional: true,
autoValue: function() {
return this.userId
},
autoform: {
type: "hidden"
}
},
studentProfileId: {
type: String,
optional: true,
autoform: {
type: "hidden"
}
}
});
Path: profile.js
Template.profile.helpers({
studentProfile: ()=> {
var id = FlowRouter.getParam('id');
return Meteor.users.findOne({_id: id});
},
studentProfileId: () => {
return FlowRouter.getParam('id');
}
)};
Path: profile.html
<template name="profile">
{{#autoForm collection="Jobs" id="Offer" type="insert"}}
{{> afQuickField name='Title'}}
{{> afQuickField name='studentUserId' value=studentProfileId}}
<button type="submit" class="btn btn-primary">Insert</button>
{{/autoForm}}
</template>
I have an app in which I'm using a template helper. I have the following code:
UI.registerHelper('ProfileNameByUserId', function(userid) {
console.log('Userid: ' + userid);
var user = Meteor.users.findOne({'_id': userid});
console.log.log('User:' + user);
return user.username
});
I'm calling this in my template as follows:
{{#each getDocuments}}
{{ProfileNameByUserId userid}}
{{/each}}
and in the template helper:
Template.documentsIndex.helpers({
getDocuments: function () {
return Documents.find({}, { sort: { createdAt: -1 }});
}
});
The publish and subscribe are as follows:
Routes.route('/documents', {
name: 'documents',
subscriptions: function (params, queryParams) {
this.register('documentsIndex', Meteor.subscribe('documents'));
},
action: function (params, queryParams) {
.....
});
}
});
Meteor.publish('documents', function () {
return Documents.find({})
});
I'm sure the userId is passed on, as a console.log statement shows the correct id. The issue is that the user is 'undefined' so it can't find the username.
I'm using SimpleSchema to define a users schema which looks as follows:
Users = Meteor.users;
Schema = {};
Schema.UserProfile = new SimpleSchema({
firstName: {
type: String,
optional: true
},
lastName: {
type: String,
optional: true
},
gender: {
type: String,
allowedValues: ['Male', 'Female'],
optional: true
},
});
Schema.User = new SimpleSchema({
username: {
type: String,
optional: true
},
emails: {
type: Array,
optional: true
},
"emails.$": {
type: Object
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date,
optional: true,
denyUpdate: true,
autoValue: function() {
if (this.isInsert) {
return new Date();
}
}
},
profile: {
type: Schema.UserProfile,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true
},
roles: {
type: [String],
optional: true
}
});
Meteor.users.attachSchema(Schema.User);
});
Replacing Meteor.users.findOne() in the template helper with Users.findOne() does not work either.
Any idea why user remains undefined?
You need to add a publication and subscription for the users that you want to show.
In the most general case in which all users are published:
Meteor.publish('allUsers', function () {
return Meteor.users.find();
});
Subscribe to this in your route and you will not have the user undefined in your helper.
Note that you should only publish the users that you need, but since I do not know you application structure I cannot give you a query for that.
I'm having some trouble with updating a user account. I use the following schema (collection2):
lib/collections/users.js
Users = Meteor.users;
var Schemas = {};
Schemas.User = new SimpleSchema({
gender: {
type: Number,
min: 1
},
s_gender: {
type: Number,
min: 1,
optional:false
},
picture: {
type: String,
custom: function() {
var base64Matcher = new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$");
var value = this.value.replace("data:image/png;base64,","");
if(!base64Matcher.test(value))
{
return 'no picture';
}
else
{
return true;
}
}
}
});
Users.attachSchema(Schemas.User);
Now I do the update with the following code:
client/templates/start.js
Users.update({_id: Meteor.userId()}, {
$set: {picture: picture, gender: gender, s_gender: s_gender}
}, {validationContext: "updateUser"}, function (error, result) {
if (error) {
errorObjs = Users.simpleSchema().namedContext("updateUser").invalidKeys();
console.log(errorObjs);
}
console.log(result);
});
The validation passes, but I only get a "0" in results (errors are null) - the update isn't working. Errors are shown if I have an empty field, so the validation is working well. If I detach the schema, the update works fine.
Did I forget something here or why isn't he updating when validation passes?
// Edit: Also I see, that Meteor doesn't create users anymore.
I believe you need to use Users.profile.foo instead of Users.foo, because Users is a special meteor collection and you can only save new fields inside the profile field. Try using Simple Schema/Collection 2 suggested User schema as a starting point (I'll copy it bellow). Notice the "profile schema" is loaded before the user schema:
Schema = {};
Schema.UserProfile = new SimpleSchema({
firstName: {
type: String,
regEx: /^[a-zA-Z-]{2,25}$/,
optional: true
},
lastName: {
type: String,
regEx: /^[a-zA-Z]{2,25}$/,
optional: true
},
birthday: {
type: Date,
optional: true
},
gender: {
type: String,
allowedValues: ['Male', 'Female'],
optional: true
},
organization : {
type: String,
regEx: /^[a-z0-9A-z .]{3,30}$/,
optional: true
},
website: {
type: String,
regEx: SimpleSchema.RegEx.Url,
optional: true
},
bio: {
type: String,
optional: true
}
});
Schema.User = new SimpleSchema({
username: {
type: String,
regEx: /^[a-z0-9A-Z_]{3,15}$/
},
emails: {
type: [Object],
optional: true
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date
},
profile: {
type: Schema.UserProfile,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true
}
});
Meteor.users.attachSchema(Schema.User);
source: https://github.com/aldeed/meteor-collection2