I have been working on extending the Meteor.users schema which work fine but after I create the first user in a Meteor.startup() and tried logging in I get a "User Not Found" error. Even though i can see the user in the mongo shell. Here is my schema:
Schemas.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
},
"firstName":{
type: String,
max: 50,
min:2
},
'middleName':{
type: String,
optional: true,
max: 50
},
"lastName":{
type: String,
max: 50,
min:2
},
"gender": {
type: String,
autoform: {
afFieldInput: {type: "select-radio-inline",},
options:
[
{label: "Male", value: "Male"},
{label: "Female", value: "Female"}
]
}
},
"branch": {
type: String,
optional: true,
autoform: {
type: "select",
options: function () {
return CompanyBranches.find().map(function (c) {
return {label: c.companyName+' - '+c.addressCity, value: c._id};
});
}
}
},
"active":{
type: String,
allowedValues: ["Yes","No"],
autoform: {
options: [
{label: "Yes", value: "Yes"},
{label: "No", value: "No"}
],
afFieldInput: {
type: "select-radio-inline"
}
}
},
services: {
type: Object,
optional: true,
blackbox: true
},
roles: {
type: [String],
optional: true,
autoform: {
options: [
{label: "Dashboard", value: "Dashboard"},
{label: "Branches", value: "Branches"},
{label: "User Profile", value: "User Profile"},
{label: "Case Managers", value: "Case Managers"},
{label: "Insurance Company", value: "Insurance Company"},
{label: "Tasks", value: "Tasks"},
{label: "Calendar", value: "Calendar"},
{label: "Contacts", value: "Contacts"},
{label: "Cases", value: "Cases"},
{label: "Requests", value: "Requests"},
{label: "Accounts", value: "Accounts"},
{label: "Reports", value: "Reports"},
{label: "Search", value: "Search"},
{label: "HR", value: "HR"}
],
afFieldInput: {
type: "select-checkbox-inline"
}
}
}
});
Meteor.users.attachSchema(Schemas.User);
This is my Meteor Startup function:
Meteor.startup(function () {
if ( Meteor.users.find().count() === 0 ) {
Accounts.createUser({
username: "leocrawf#gmail.com",
email:"leocrawf#gmail.com",
password: "leoten",
firstName: "Leocrawf",
lastName: "Stewart",
gender:"Male",
active: "Yes"
}, function (error) {
if (error) {
console.log("Cannot create user");
}
});
}
});
on the server i am doing this in the Accounts.onCreateUser():
Accounts.onCreateUser(function(options, user) {
user = options || {};
user.username = options.username;
user.firstName = options.firstName;
user.lastName = options.lastName;
user.active = options.active;
user.gender = options.gender;
// Returns the user object
return user;
});
When I query the mongo shell i get this:
meteor:PRIMARY> db.users.find().pretty()
{
"_id" : "pFurR8iDYWJcX9rus",
"username" : "leocrawf#gmail.com",
"firstName" : "Leocrawf",
"lastName" : "Stewart",
"gender" : "Male",
"active" : "Yes",
"services" : {
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2016-02-05T23:13:38.364Z"),
"hashedToken" : "vs5xVlKL59yVTO/fbKbSnar38I8ILAruj2W1YecQ2Io="
}
]
}
}
}
It doesn't look like you're setting up the profile correctly when creating the user:
Instead of:
Accounts.createUser({
username: "leocrawf#gmail.com",
email:"leocrawf#gmail.com",
password: "leoten",
firstName: "Leocrawf",
lastName: "Stewart",
gender:"Male",
active: "Yes"
},
Try:
Accounts.createUser({
username: "leocrawf#gmail.com",
email: "leocrawf#gmail.com",
password: "leoten",
profile: {
firstName: "Leocrawf",
lastName: "Stewart",
gender: "Male",
active: "Yes"
}
},
Also I recommend active: true instead of active: "Yes" to use a boolean instead of a string. It doesn't look like you've defined active or gender in your schema either btw.
Related
The expected XML format is as per below:
<c:condition>
<a:condition>
<fieldname>fieldName</fieldname>
<fieldtest>fieldTest</fieldtest>
<fieldvalues>
<fieldvalue>fieldValue</fieldvalue>
</fieldvalues>
</a:condition>
<operator>operator</operator>
<a:condition>
...<some>
</a:condition>
</c:condition>
The <a:condition> and the <operator> both needs to be in a collection as both can have as many as required by the XML request.
EDITED Type:elements code as below:
{{
var MyModule = {
name: 'MyModule',
typeInfos: [{
type: 'classInfo',
localName: 'ElementsType',
propertyInfos: [{
type: 'elements',
name: 'c:condition',
wrapperElementName: {
localPart: 'condition',
namespaceURI: 'http://us.xomplex',
prefix: 'c'
},
collection: true,
elementTypeInfos: [{
elementName: {
localPart: 'condition',
namespaceURI: 'http://us.xomplexio',
prefix: 'a'
},
typeInfo: 'MyModule.SubAtomic'
}, {
elementName: 'operator',
typeInfo: 'String'
}]
}]
},
{
type: 'classInfo',
localName: 'SubAtomic',
propertyInfos:[{
type: 'element',
name: 'fieldName',
elementName: 'fieldName',
typeInfo: 'String'
},
{
type: 'element',
name: 'fieldTest',
elementName: 'fieldTest',
typeInfo: 'String'
}]
}],
elementInfos: [{
elementName: 'root',
typeInfo: 'MyModule.ElementsType'
}]
};
console.log("creating unmarsaller");
var context = new Jsonix.Context([MyModule]);
var unmarshaller = context.createUnmarshaller();
var unmarshalled = unmarshaller.unmarshalString('<root><c:condition xmlns:c="http://us.xomplex"><a:condition xmlns:a="http://us.xomplexio">one</a:condition><operator>2</operator><a:condition xmlns:a="http://us.xomplexio"><fieldName>unmra</fieldName><fieldTest>Beneed</fieldTest></a:condition><a:condition xmlns:a="http://us.xomplexio">four</a:condition><operator>AND</operator><operator>4</operator></c:condition></root>');
console.log("unmarshalled");
console.log(unmarshalled);
var marshaller = context.createMarshaller();
var marshalled = marshaller.marshalString({
name: {
localPart: 'root'
},
//Marshalling - not working....
value: {
//'c:condition': ['one', 2, 'unmra', 'four', 10,4]
'c:condition': [
['Field','Test'],9
]
}
});
console.log(marshalled);
}}
EDITED Looks like elements can fulfill my requirements. Unmarshalling works too. Now I only need to figure out how to marshall it from Json format. Any advice will be greatly appreciated
Not exactly as you want it.
You can use elements or elementReferences property to declare a collection property which would contain different elements as items. Something like:
{
type: 'elementRefs',
name: 'acondition',
collection: true,
elementTypeInfos: [{
elementName: 'condition',
typeInfo: 'DOXML.Atomicon'
}, {
elementName: 'operator',
typeInfo: 'String'
}]
}
This property would contain condition or operator ins any quantity or order. But this does not guarantee that you have the same number of them or that it's always condition followed by operator. If this is what you want, consider wrapping condition and operator pair into an element like conditionalOperator.
This is my solution to the problem:
var MyModule = {
name: 'MyModule',
typeInfos: [{
type: 'classInfo',
localName: 'ElementsType',
propertyInfos: [{
type: 'elements',
name: 'c:condition',
wrapperElementName: {
localPart: 'condition',
namespaceURI: 'http://us.xomplex',
prefix: 'c'
},
collection: true,
elementTypeInfos: [{
elementName: {
localPart: 'condition',
namespaceURI: 'http://us.xomplexio',
prefix: 'a'
},
typeInfo: 'MyModule.SubAtomic'
}, {
elementName: 'operator',
typeInfo: 'String'
}]
}]
},
{
type: 'classInfo',
localName: 'SubAtomic',
propertyInfos:[{
type: 'element',
name: 'fieldName',
elementName: 'fieldName',
typeInfo: 'String'
},
{
type: 'element',
name: 'fieldTest',
elementName: 'fieldTest',
typeInfo: 'String'
},
{
type: 'element',
name: 'fieldValues',
elementName: 'fieldValues',
typeInfo: 'MyModule.SubSubAtoms'
}]
},
{
type: 'classInfo',
localName: 'SubSubAtoms',
propertyInfos:[
{
type: 'element',
name: 'fieldValue',
collection: true,
elementName: 'fieldValue',
typeInfo: 'String'
}
]
}
],
elementInfos: [{
elementName: 'root',
typeInfo: 'MyModule.ElementsType',
},
{
elementName: 'atoms',
typeInfo:'MyModule.SubAtomic'
}
]
};
console.log("creating unmarsaller");
var context = new Jsonix.Context([MyModule]);
var unmarshaller = context.createUnmarshaller();
var unmarshalled = unmarshaller.unmarshalString('<root><c:condition xmlns:c="http://us.xomplex"><a:condition xmlns:a="http://us.xomplexio">one</a:condition><operator>2</operator><a:condition xmlns:a="http://us.xomplexio"><fieldName>unmra</fieldName><fieldTest>Beneed</fieldTest></a:condition><a:condition xmlns:a="http://us.xomplexio">four</a:condition><operator>AND</operator><operator>4</operator></c:condition></root>');
console.log("unmarshalled");
console.log(unmarshalled);
var marshaller = context.createMarshaller();
var marshalled = marshaller.marshalString({
name: {
localPart: 'root'
},
value: {
'c:condition': [
"9",
{ name:
{
localPart: 'atoms'
},
fieldName: "rating",
fieldTest: "equals",
fieldValues: {
fieldValue: ["563"]
} ,
TYPE_NAME: 'MyModule.SubAtomic'
},
"AND",
{ name:
{
localPart: 'atoms'
},
fieldName: "price",
fieldTest: "between",
fieldValues: {
fieldValue: ["150", "300"]
} ,
TYPE_NAME: 'MyModule.SubAtomic'
}] //end of c:condition value
}
});
console.log(marshalled);
Done! Thank you #lexicore, your guides were a great help!
I have this schema:
AdsSchema = new SimpleSchema({
title: {
type: String,
label: "Title"
},
_cityId: {
type: String,
label: "City ID"
},
_categoryId: {
type: String,
label: "Category ID"
},
insertedDateTime: {
type: Date,
label: "Inserted Date Time",
autoValue: function() {
if (this.isInsert) {
return new Date();
} else if (this.isUpsert) {
return {$setOnInsert: new Date()};
} else {
this.unset(); // Prevent user from supplying their own value
}
}
},
insertedBy: {
type: String,
label: "Inserted By"
defalutValue: Meteor.user().username
},
price: {
type: Number,
label: "Price"
},
image: {
type: Object,
label: "Image",
optional: true
},
email: {
type: String,
label: "Email"
},
phoneNumber: {
type: String,
label: "Phone Number",
optional: true
},
desc: {
type: String,
label: "Description",
autoform: {
afFieldInput: {
type: "textarea",
rows: 10
}
}
},
quickOrNot: {
type: Boolean,
label: "Quick Or Not",
}
});
I use quickForm for insert to mongoDB, whit following code:
{{> quickForm schema="AdsSchema" collection="Ads" id="insBaseAds" type="insert"}}
and autoForm generate for me a form with all of schema's fields.
but I want only limit fields to show to user on autform, for example these fields:
title, price, image, email, phoneNumber, desc
and I fill some fields my self, for example these fields:
_cityId: "test",
_categoryId: "test",
insertBy: "test"
how can I use quickForm?
You can use afQuickfields
{{>afQuickFields fields="title, price, image, email, phoneNumber, desc"}}
else you can use type 'hidden' in schema
_cityId: {
type: String,
label: "City ID",
autoform:{
type:"hidden"
}
}
I am having problems with Collection2 and autoform. Here is my collection
Customers = new Mongo.Collection("customers");
Customers.allow({
insert: function(userId, doc) {
return !!userId;
}
});
CustomerSchema = new SimpleSchema({
name: {
type: String,
label: "Name"
},
address: {
type: String,
label: "Address"
},
amount: {
type: Number,
label: "Amount"
},
bvn: {
type: String,
label: "BVN"
},
type: {
type: String,
label: "Sale Type"
},
saleDate: {
type: Date,
label: "Transaction Date",
autoValue: function() {
return new Date()
},
autoform: {
type: "hidden"
}
},
passport: {
type: String,
label: "Passport Number"
},
source: {
type: String,
label: "Source"
},
tickets: {
type: Boolean,
label: "Tickets"
},
visa: {
type: Boolean,
label: "Visa"
},
invoice: {
type: Boolean,
label: "Invoice"
},
nextSaleDate: {
type: Date,
label: "Next Sale Date",
autoValue: function () {
var thisDate = new Date();
var dd = thisDate.getDate();
var mm = thisDate.getMonth() + 3;
var y = thisDate.getFullYear();
var nextDate = dd + '/'+ mm + '/'+ y;
return nextDate;
},
autoform: {
type: "hidden"
}
},
author: {
type: String,
label: "Author",
autoValue: function () {
return this.userId
},
autoform: {
type: "hidden"
}
}
});
Customers.attachSchema(CustomerSchema);
I have published and subscribed to the collections in separate publish and subscribe javascript files with methods Meteor.publish('customers', function() {
return Customers.find({author: this.userId});
}); and Meteor.subscribe("customers"); respectively. Here is the html code for insert
<template name="NewCustomer">
<div class="new-customer">
{{>quickForm collection="Customers" id="insertCustomerForm" type="insert" class="new-customer-form"}}
</div>
</template>
But when i bootup the server and add a new customer, it doesn't work. Can anyone help me out? Thank you
I sorted it out. This field in the collection
nextSaleDate: {
type: Date,
label: "Next Sale Date",
autoValue: function () {
var thisDate = new Date();
var dd = thisDate.getDate();
var mm = thisDate.getMonth() + 3;
var y = thisDate.getFullYear();
var nextDate = dd + '/'+ mm + '/'+ y;
return nextDate;
},
autoform: {
type: "hidden"
}
},
is the one causing the issue. Thank you all for your input
I have a collection called Assesments and another collection called ChairAssesments, I have these defined separately now, but for later use I want to insert a value by default into ChairAssesments whenever I insert value in Assesments.
So I want to do something like
Assesments.after.insert(function (userId, doc) {
ChairAssesments.insert({ assesmentId: doc._id });
});
but this is not working
Assesment collection
Assesments = new Mongo.Collection('assesments');
ChairAssesments = new Mongo.Collection('chairassesments');
Assesments.after.insert(function (userId, doc) {
ChairAssesments.insert({ assesmentId: doc._id });
});
Assesments.before.insert(function (userId, doc) {
doc.createdAt = new Date();
doc.assesmentDate = new Date();
});
Assesments.attachSchema(new SimpleSchema({
name: {
type: String,
label: 'First Name',
autoform: {
'label-type': 'placeholder',
placeholder: 'First Name'
}
},
email: {
type: String,
label: 'Email',
autoform: {
'label-type': 'placeholder',
placeholder: 'Email'
}
},
category: {
type: String,
label: 'Category',
optional: true,
autoform: {
options: [
{value: 'General', label: 'General'},
{value: 'Reported', label: 'Reported'},
{value: 'Follow Up', label: 'Follow Up'}
],
type: 'select-radio'
}
},
assesmentDate: {
type: Date,
label: 'Assesment Date',
optional: true
},
location: {
type: String,
label: 'Location',
autoform: {
'label-type': 'placeholder',
placeholder: 'Location'
},
max: 200
},
chairAssesments:{
type: ChairAssesments
}
}
));
if (Meteor.isServer) {
Assesments.allow({
insert: function (doc) {
return true;
},
update: function (doc, fieldNames, modifier) {
return true;
},
remove: function (doc) {
return true;
}
});
}
ChairAssesment collection
ChairAssesment = new Mongo.Collection('chairassesment');
ChairAssesment.before.insert(function (userId, doc) {
doc.createdAt = new Date();
});
ChairAssesment.attachSchema(new SimpleSchema({
assesmentId: {
type: String
},
height: {
type: String,
label: 'Chair Height (Open hip angle)',
optional: true,
autoform: {
options: [
{value: 'Very Less', label: 'Very Less'},
{value: 'Medium', label: 'Medium'},
{value: 'Very High', label: 'Medium'}
],
type: 'select-radio'
}
},
backSupport: {
type: String,
label: 'Back Support',
optional: true,
autoform: {
options: [
{value: 'Very Less', label: 'Very Less'},
{value: 'Medium', label: 'Medium'},
{value: 'Very High', label: 'Medium'}
],
type: 'select-radio'
}
},
seatDepth: {
type: String,
label: 'Seat Depth',
optional: true,
autoform: {
options: [
{value: 'Very Less', label: 'Very Less'},
{value: 'Medium', label: 'Medium'},
{value: 'Very High', label: 'Medium'}
],
type: 'select-radio'
}
},
tiltLock: {
type: String,
label: 'Tilt Lock',
optional: true,
autoform: {
options: [
{value: 'Very Less', label: 'Very Less'},
{value: 'Medium', label: 'Medium'},
{value: 'Very High', label: 'Medium'}
],
type: 'select-radio'
}
},
armRests: {
type: String,
label: 'Arm Rests',
optional: true,
autoform: {
options: [
{value: 'Very Less', label: 'Very Less'},
{value: 'Medium', label: 'Medium'},
{value: 'Very High', label: 'Medium'}
],
type: 'select-radio'
}
},
fidgeting: {
type: String,
label: 'Fidgeting',
optional: true,
autoform: {
options: [
{value: 'Very Less', label: 'Very Less'},
{value: 'Medium', label: 'Medium'},
{value: 'Very High', label: 'Medium'}
],
type: 'select-radio'
}
},
standingUp: {
type: String,
label: 'Standing Up',
optional: true,
autoform: {
options: [
{value: 'Very Less', label: 'Very Less'},
{value: 'Medium', label: 'Medium'},
{value: 'Very High', label: 'Medium'}
],
type: 'select-radio'
}
}
}
));
if (Meteor.isServer) {
ChairAssesment.allow({
insert: function (doc) {
return true;
},
update: function (doc, fieldNames, modifier) {
return true;
},
remove: function (doc) {
return true;
}
});
}
Insert method of a collection takes object (JSON) as a first parameter. Read more about JavaScript objects here: http://www.codermania.com/javascript/lesson/1r/objects
Read more about insert method in Meteor docs: http://docs.meteor.com/#/full/insert
Your code should look like this:
Assesments.after.insert(function (userId, doc) {
ChairAssesments.insert({ assesmentId: doc._id });
});
I am using autoform and collection2 package and making a form in meteor. As of now i put some hard-coded option for country-state-city dropdown and insert-update is working fine. Now I want for the first time only country dropdown is enable other two are disable. Based on Country selection the states dropdown will populate and enable. Then based on State selection City Should Populate.
I don't want to do this manually. Is there any way to do this using autoform / collection2 features??? My code sample is as follows:
Collection2 Schema:
country:{
type: String,
label : "Country",
autoform: {
afFieldInput: {
type: "select"
},
options: function () {
return [
{label: 'Country1', value: 'Country1'},
{label: 'Country2', value: 'Country2'},
{label: 'Country3', value: 'Country3'},
{label: 'Country4', value: 'Country4'}
];
}
}
},
state:{
type: String,
label : "State",
autoform: {
afFieldInput: {
type: "select"
},
options: function () {
return [
{label: 'State1', value: 'State1'},
{label: 'State2', value: 'State2'},
{label: 'State3', value: 'State3'},
{label: 'State4', value: 'State4'}
];
}
}
},
city:{
type: String,
label : "City",
autoform: {
afFieldInput: {
type: "select"
},
options: function () {
return [
{label: 'City1', value: 'City1'},
{label: 'City2', value: 'City2'},
{label: 'City3', value: 'City3'},
{label: 'City4', value: 'City4'}
];
}
}
},
HTML ::
{{> afQuickField name='country' template="bootstrap3-horizontal" label-class="col-sm-4" input-col-class="col-sm-8"}}
{{> afQuickField name='state' template="bootstrap3-horizontal" label-class="col-sm-4" input-col-class="col-sm-8"}}
{{> afQuickField name='city' template="bootstrap3-horizontal" label-class="col-sm-4" input-col-class="col-sm-8"}}
Any Help??
I think this is somewhat the idea you have, https://jsfiddle.net/bdhacker/eRv2W/
// Countries
var country_arr = new Array("Afghanistan", "Albania", "Algeria", "American Samoa", "Angola", "Anguilla", "Antartica"...
// States
var s_a = new Array();
s_a[0] = "";
s_a[1] = "Badakhshan|Badghis|Baghlan|Balkh|Bamian|Farah|Faryab|Ghazni|Ghowr|Helmand|Herat|Jowzjan|Kabol|Kandahar|Kapisa|Konar|Kondoz|Laghman|Lowgar|Nangarhar|Nimruz|Oruzgan|Paktia|Paktika|Parvan|Samangan|Sar-e Pol|Takhar|Vardak|Zabol";...
you can extract the data from this and adjust to your app. Hope it helps
i think you can set the inputs of state and city to be disabled
country:{
type: String,
label : "Country",
autoform: {
afFieldInput: {
type: "select"
},
options: function () {
return [
{label: 'Country1', value: 'Country1'},
{label: 'Country2', value: 'Country2'},
{label: 'Country3', value: 'Country3'},
{label: 'Country4', value: 'Country4'}
];
}
}
},
state:{
type: String,
label : "State",
autoform: {
afFieldInput: {
type: "select",
disabled:true
},
options: function () {
return [
{label: 'State1', value: 'State1'},
{label: 'State2', value: 'State2'},
{label: 'State3', value: 'State3'},
{label: 'State4', value: 'State4'}
];
}
}
},
city:{
type: String,
label : "City",
autoform: {
afFieldInput: {
type: "select",
disabled:true
},
options: function () {
return [
{label: 'City1', value: 'City1'},
{label: 'City2', value: 'City2'},
{label: 'City3', value: 'City3'},
{label: 'City4', value: 'City4'}
];
}
}
},
and use Template event to enable the options
Template.YOURTEMPLATENAME.events({
'change input[name="country"]' :function(){
if ($('input[name="country"]').value() != ''){
$('input[name="state"]').attr('disabled','');
}else {
$('input[name="state"]').attr('disabled','disabled');
}
},
'change input[name="state"]' :function(){
if ($('input[name="state"]').value() != ''){
$('input[name="city"]').attr('disabled','');
}else {
$('input[name="city"]').attr('disabled','disabled');
}
}
});