Related
I have two separate schemas that use the same field. I've tried to create schemaComponents so that I can update both schemas in one location however I get an error Error: Invalid definition for school.$ field. when I use it. I'm not sure what I'm doing wrong here, I was under the impression this was allowed.
Path: SchemaComponents.js
SchemaComponents = {
schools: {
type: [String],
optional: true,
autoform: {
options: [
{label: "School One", value: 'SchoolOne'},
{label: "School Two", value: 'SchoolTwo'},
{label: "School Three", value: 'SchoolThree'},
]
}
}
};
Path: StudentSchema.js
import from '../components/SchemaComponents.js';
StudentSchema = new Mongo.Collection("studentSchema");
var Schemas = {};
Schemas.StudentSchema = new SimpleSchema({
school: SchemaComponents.schools,
});
StudentSchema.attachSchema(Schemas.StudentSchema);
Path: TeacherSchema.js
import from '../components/SchemaComponents.js';
TeacherSchema = new Mongo.Collection("teacherSchema");
var Schemas = {};
Schemas.TeacherSchema = new SimpleSchema({
school: SchemaComponents.schools,
});
TeacherSchema.attachSchema(Schemas.TeacherSchema);
You defined SchemaComponent as a simple object and not as a SimpleSchema object. To reuse your schools definition do:
let schoolsSchema = new SimpleSchema({
schools: {
type: [String],
optional: true,
autoform: {
options: [
{label: "School One", value: 'SchoolOne'},
{label: "School Two", value: 'SchoolTwo'},
{label: "School Three", value: 'SchoolThree'},
]
}
}
});
Then you can do:
Schemas.TeacherSchema = new SimpleSchema({
school: {
type: schoolsSchema
}
});
I might be thinking about this the wrong way, so please feel free to correct my thinking.
I'm using simpleSchema and I have a section of code which is used in more than one schema. Is there a way to create an individual component and import it into each schema, so that when I need to update the component I don't have to update it in multiple locations?
Path: resuableComponent
type: String,
optional: true,
autoform: {
type: "select",
options: function () {
return [
{label: "School logo 1", value: 'url'},
{label: "School logo 2", value: 'url'},
{label: "School logo 3", value: 'url'},
];
},
}
Path: studentCollection.js
Schemas.Student = new SimpleSchema({
studentUserId: {
type: String,
},
school: {
type: String,
optional: false
},
**resuableComponent**
});
Path: teacherCollection.js
Schemas.Teacher = new SimpleSchema({
teacherUserId: {
type: String,
},
school: {
type: String,
optional: false
},
**resuableComponent**
});
You could move the reusable objects into a different file that should be visible on both client and server if you are using SimpleSchema.
Example based on your question:
lib/schema-components.js :
SchemaComponents = {
school: {
type: String,
optional: false
},
// ...
// more reusable components here
};
someCollectionFile.js :
Schemas.Student = new SimpleSchema({
studentUserId: {
type: String
},
school: SchemaComponents.school,
// ...
});
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.
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 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');
}
}
});