Meteor - Validations on structured data with simple schema / autoform - meteor

I'm have some simple schema which I'm using with autoform:
Schemas.studentRecord = new SimpleSchema({
'common.FName': { // note that this field is nested
type: String,
optional: false,
label: "First Name",
max: 50
}
});
Inserting a document using this schema works fine. Updating it does too. The problem is that when I'm nesting data the optional: false validation is not running, it's just ignored - meaning I can insert empty documents. However use the following schema without nesting it works:
Schemas.studentRecord = new SimpleSchema({
'commonFName': { // note that this field is no longer nested
type: String,
optional: false,
label: "First Name",
max: 50
}
});
So my question is, can I validate nested data or must I keep it unstructured for validation?

Solution was to include 'common' as part of the schema:
'common': {
type: Object
}

Related

How do I reference another collection as a field in a Meteor Schema

I'm using meteor simple schema, and autoform. I would like to have a reference to one type of object in the schema of the other. The two schemas are defined in separate files, I would also like to populate autoform with a dropdown of the possible references, and I'm unclear how to do this.
I've tried
venue:{
type: Venues,
label: "Venue",
},
and
venue:{
type: SimpleSchema.Venues,
label: "Venue",
},
and neither works
First you have to define your schema like this:
VenueSchema = new SimpleSchema({
title: {
type: String,
label: "Title",
max: 200
}
})
Than you can in another schema declare an attribute Venue
CustomerSchema = new SimpleSchema({
venue: {
type: VenueSchema
},
//an array of venues
venues: {
type: [VenueSchema],
minCount: 1
}
});
Take a look on basic usage of simpleSchema docs -> https://github.com/aldeed/meteor-simple-schema#basic-usage
I hope that helps.

Simple Schema and multiple forms

I have a user profile schema that looks sort of like this:
Schema.UserProfile = new SimpleSchema({
name: {
type: String,
optional: false
},
gender: {
type: String,
optional: false,
allowedValues: ['Male', 'Female']
},
location: {
type: String,
optional: false
},
age: {
type: Number,
optional: false
}
}
My registration form requires the user to select their gender on it. Once registered, the user is presented with another form to fill out the rest of the data: name, location, and age.
Here's the problem: When the user tries to register, I get the error: Name is required. The user isn't suppose to enter their name until they register.
What is the proper approach to only validating data that is actually being saved on a specific form?
EDIT
Here is my registration script:
var data = {};
var profile = {};
data.email = $('#email').val();
data.password = $('#password').val();
profile.gender = $('#gender').val();
data.profile = profile;
Accounts.createUser(data, function (error) {
// do
// ERROR: Name is required
});
When the user actually registers, they're presented with a form to fill the other data in. The form submit calls a method that the tries to update the profile object.
By using the option optional: false you are making it mandatory whenever creating the object.
One solution could be to use myCollection.insert(); with the flag validate: false instead of createUser().
e.g.
myCollection.insert(doc, {validate: false});
This will not trigger the error, since is skipping the validation.
I would personally not use this way, but it might be a solution.
You can use SimpleSchema's pick command to select certain elements from a schema. That way you can have multiple schemas derived from the same original schema definition.
Schemas.UserProfileRegistration1 = Schemas.UserProfile.pick(['gender']);
Schemas.UserProfileRegistration2 = Schemas.UserProfile.pick(['name', 'location', 'age']);
https://github.com/aldeed/meteor-simple-schema#extracting-simpleschemas

autoform won't render select option field

I have an issue regarding collection2 with relationships and autoform.
I try to implement an 1:n relationship, where each object has exactly 1 objectType, while to each objectType multiple objects can be referred to.
My schema looks as follows:
// register collections
Objects = new Mongo.Collection('objects');
ObjectTypes = new Mongo.Collection('objectTypes');
// define schema
var Schemas = {};
Schemas.ObjectType = new SimpleSchema({ // object type schema
name: {
type: String
}
});
Schemas.Object = new SimpleSchema({ // object schema
type: {
type: ObjectTypes.Schema,
optional: true
},
title: {
type: String
}
});
// attach schemas
ObjectTypes.attachSchema(Schemas.ObjectType);
Objects.attachSchema(Schemas.Object);
My autoform looks like this:
{{> quickForm collection="Objects" id="insertTestForm" type="insert"}}
I actually would expect a select option field for my type attribute, however, a text input appears. Anyone knows why?
According to the documentation [1], it should be a select option field:
If you use a field that has a type that is a Mongo.Collection instance, autoform will automatically provide select options based on _id and name fields from the related Mongo.Collection. You may override with your own options to use a field other than name or to show a limited subset of all documents. You can also use allowedValues to limit which _ids should be shown in the options list.
[1] https://github.com/aldeed/meteor-collection2/blob/master/RELATIONSHIPS.md#user-content-autoform
EDIT
If I use
type: ObjectTypes,
instead of
type: ObjectTypes.Schema,
my app crashes, throwing the following error:
Your app is crashing. Here's the latest log.
/Users/XXX/.meteor/packages/meteor-tool/.1.1.3.ik16id++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:245
throw(ex);
^
RangeError: Maximum call stack size exceeded
Exited with code: 8
Your application is crashing. Waiting for file change.
Your type isn't "a Mongo.Collection instance" like the documentation says; it's a Schema. Try this:
Schemas.Object = new SimpleSchema({
type: {
type: ObjectTypes,
optional: true
},
...
Since nobody could help me solve this incident, I came up with an alternate solution:
// register collections
Objects = new Mongo.Collection('objects');
ObjectTypes = new Mongo.Collection('objectTypes');
// define schema
var Schemas = {};
Schemas.Object = new SimpleSchema({ // object schema
type: {
type: String,
optional: true,
autoform: {
return ObjectTypes.find().map(function(c) {
return{label: c.name, value: c._id}
});
}
},
// ...
});
// attach schema
Objects.attachSchema(Schemas.Object);
As u can see, I manually map the attributes I need from the objectTypes collection into the autoform attribute. Since it returns an array of objects, containing the label and value attributes, autoform will automatically render a select option.

How to create AutoForm field in Meteor to select a record from another collection and save it as a subdocument?

I've been struggling with this for a couple of hours and I can't find a good solution so maybe someone can shed a light on this.
I have a simple schema like this:
var groupschema = new SimpleSchema({
name: {
label: 'Name',
type: String
},
description: {
label: 'Description',
type: String
}
}
And I have another one:
var itemschema = new SimpleSchema({
name: {
label: 'Type:',
type: String
},
details: {
label: 'Details',
type: String
},
group: [groupschema] // <--- this is my main interest
}
If I use the above code sample AutoForm will generate an "inner form" which is quite cool actually for some puporse (e.g. for a contact to have an array of adresses or phone numbers) but for me I would like a drop-down select with the name of the group and when I click on the Insert/Update button (depending on the current form) I would like to add the whole group document to the inserted/updated item document as a subdocument.
Something like this will be inserted to the mongodb:
{
_id: the generated mongoid,
name: "This is a type",
details: "There are some thing to know about this type",
group:{
name: "Cool group",
description: "This is a really cool group"
}
}
The actual documents are far more complicated the above example is just an oversimplified version.
I've stopped writing this question yesterday and tried to do my own version.
My - half baked - solution is:
introducing a new field in the schema named groupselect (type string, autoform type: select)
populate it's contents with a Collection.find().map() lookup
groupselect: {
type: String,
label: 'Group',
optional: true,
blackbox: true,
autoform:{
type: "select",
options : function() {
return Issuegroup.find().map(function (c) {
return {label: c.name , value: c._id};
});
}
}
},
using autoform hooks before insert I assign the subdocument to the real fiel group = Group.find({_id:doc.groupselect}) and I remove the helper field from the doc
using the same technique in the before update hook also for an update form
The problem I seem to be unable to solve in a clean way is to set the default value of the helper field 'groupselect' when the update form displays. I've tried the docToForm hooks but no luck.
Isn't this somehow a very common problem? I imagine there has to be a proper solution for this so I bet that I am missing something very obvious and hopefully someone will point it out for me.
Thanks

Some questions on Simple-Schema for Meteor

For those who use Simple Schema for Meteor validation I've got some questions (after having used it for a while):
1.
Does SimpleSchema support square bracket notation? All the examples show it using dot notation. I did the following square bracket implementation:
Schemas.NamesCollection = new SimpleSchema({
name: {
type: Object
},
"name[first_name]" : {
type: String,
optional: false,
label: "First Name"
},
"name[last_name]" : {
type: String,
optional: false,
label: "Last Name"
}
});
{{> afQuickField name="name[first_name]"}}
{{> afQuickField name="name[last_name]"}}
I noticed that the form validation worked just fine as I'm filling out the form, but the final insertion of the data into the collection fails with a validation error (the same exact error that had passed earlier on the form validation but is now failing on insertion).
There are a lot of reasons to use square bracket notation, obviously. Dot notation has tons of limitations, despite being more readable.
2. Looking at the example above defining the schema, the keys in the schema have to be the full path in the object. You have to declare name[first_name] to assign a schema to it, which means that you're not only defining the properties of first_name, but you're also defining the structure of the object. first_name has to be nested inside name.
You can't, for example, just do
Schemas.NamesCollection = new SimpleSchema({
name: {
type: Object
},
first_name : {
type: String,
optional: false,
label: "First Name"
},
last_name : {
type: String,
optional: false,
label: "Last Name"
}
});
And then proceed to store first_name and last_name inside of name, can you?

Resources