How should I insert into Meteor collection using autoform/collection2? - meteor

I'm trying to do the autoform books example using Meteor. How exactly should I do the Books.insert ?
I see the example:
Books.insert({title: "Ulysses", author: "James Joyce"}, function(error, result) {
//The insert will fail, error will be set,
//and result will be undefined or false because "copies" is required.
//
//The list of errors is available on
//`error.invalidKeys` or by calling
Books.simpleSchema().namedContext().invalidKeys()
});
I'm not entirely sure how I should hook this up with the rest of my code:
if (Meteor.isClient) {
Books = new Meteor.Collection("books");
var Schemas = {};
Schemas.Book = new SimpleSchema({
title: {
type: String,
label: "Title",
max: 200,
optional: true
},
author: {
type: String,
label: "Author",
optional: true
},
copies: {
type: Number,
label: "Number of copies",
min: 0,
optional: true
},
lastCheckedOut: {
type: Date,
label: "Last date this book was checked out",
optional: true
},
summary: {
type: String,
label: "Brief summary",
optional: true,
max: 1000
}
});
Books.attachSchema(Schemas.Book);
}
Can anyone give me any advice on this?
I'm thinking that I would need something like this:
Template.bookform.events({
'click btn.submit': function () {
var form = document.getElementById("formID").value;
Books.insert(form);
}
});
Thanks in advance! :)

I have never used autoform but in the documentation it says that it already gives you "automatic insert and update events, and automatic reactive validation".
So there should be no need to specify your own event handler.
In the docs you will also find the books example. I am just copying from there:
JS
Books = new Meteor.Collection("books", {
schema: {
title: {
type: String,
label: "Title",
max: 200
},
author: {
type: String,
label: "Author"
},
copies: {
type: Number,
label: "Number of copies",
min: 0
},
lastCheckedOut: {
type: Date,
label: "Last date this book was checked out",
optional: true
},
summary: {
type: String,
label: "Brief summary",
optional: true,
max: 1000
}
}
});
if (Meteor.isClient) {
Meteor.subscribe("books");
}
if (Meteor.isServer) {
Meteor.publish("books", function () {
return Books.find();
});
}
HTML
<head>
<title>Book example</title>
</head>
<body>
{{> insertBookForm}}
</body>
<template name="insertBookForm">
{{> quickForm collection="Books" id="insertBookForm" type="insert"}}
</template>

Related

Saving API call result to a collection but recieving errors while setting up a SimpleSchema

I have a Meteor method which does an API call, then the response of the call is saved to the users collection. I'm using the Collection2 package with my project and I'm a little bit lost setting up my SimpleSchema for this.
Here is what the JSON response looks like from the API call:
[{"keyword":"2i","url":"http://example.com","title":"Example","timestamp":"2016-11-05
08:54:42","ip":"00.00.00.000","clicks":"2","user":"HweoSCY2ujscjJ9Zl"},{"keyword":"2j","url":"http://example.com","title":"YouTube","timestamp":"2016-11-06
02:11:18","ip":"00.00.00.000","clicks":"1","user":"HweoSCY2ujscjJ9Zl"},{"keyword":"2k","url":"http://example.com","title":"YouTube","timestamp":"2016-11-08
03:35:12","ip":"00.00.00.000","clicks":"0","user":"HweoSCY2ujscjJ9Zl"}]
Here's currently how I've been able to save this data to the users collection:
Meteor.users.update(Meteor.userId(), {
$set: { 'shortURLs.URLS': result.data }
});
This works and looks like this in the db:
My issue is that I'd like to have a SimpleSchema setup for this so that the "timestamp" will be saved as a Date instead of a String, but everytime I try and create a schema for it I just receive errors like "After filtering out keys not in the schema, your modifier is now empty". I have tried a lot of different variations to try and make it work but none of them have been successful, here's just currently where it's at:
Schema.ShortURLs = new SimpleSchema({
shortURLs: {
type: Object
},
'shortURLs.$': {
type: Object
},
'shortURLs.$.keyword': {
type: String,
optional: true,
label: "Keyword"
},
'shortURLs.$.url': {
type: String,
optional: true,
label: "URL"
},
'shortURLs.$.title': {
type: String,
optional: true,
label: "Title"
},
'shortURLs.$.timestamp': {
type: Date,
optional: true,
label: "Timestamp"
},
'shortURLs.$.ip': {
type: String,
optional: true,
label: "IP"
},
'shortURLs.$.clicks': {
type: String,
optional: true,
label: "Clicks"
},
'shortURLs.$.user': {
type: String,
optional: true,
label: "User"
},
});
This is then attached apart of a User Simple Schema:
...
shortURLs: {
type: Schema.ShortURLs,
optional: true
},
...
And I have that attached to the users collection:
Meteor.users.attachSchema(Schema.User);
I don't think there's an issue with how I have it attached as I have other SimpleSchemas setup the same way and they're working fine, I believe the issue is how I have this particular one written. Any help here would be extremely appreciated.
You need to define the shortURLs type in the Meteor.users collection as type: [Schema.ShortURLs], i.e. a list of type Schema.ShortURLs
Schema = {}
Schema.ShortURLs = new SimpleSchema({
keyword: {
type: String,
optional: true,
label: "Keyword"
},
url: {
type: String,
optional: true,
label: "URL"
},
title: {
type: String,
optional: true,
label: "Title"
},
timestamp: {
type: Date,
optional: true,
label: "Timestamp"
},
ip: {
type: String,
optional: true,
label: "IP"
},
clicks: {
type: String,
optional: true,
label: "Clicks"
},
user: {
type: String,
optional: true,
label: "User"
},
});
Schema.User = new SimpleSchema({
...
shortURLs: {
type: [Schema.ShortURLs],
optional: true
},
...
});
...
Meteor.users.attachSchema(Schema.User);

How to create reusable component with simpleSchema

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,
// ...
});

meteor - lukemadera:autoform-googleplace

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.

meteor autoform required validation not working with nested schema

Below is my nested schema. name.first is required. but when I submit the form it not validating, it allows empty string. did I missed anything? or How to fix this issue?
Schema.UserProfile = new SimpleSchema({
'name.first': {
type: String,
max: 50,
label: "First name"
},
'name.last': {
type: String,
optional: true,
max: 50,
label: "Last name"
}
});
Schema.User = new SimpleSchema({
profile: {
type: Schema.UserProfile,
optional: true
},
});
Meteor.users.attachSchema(Schema.User);
form:
{{#autoForm id="profile" type="method-update" meteormethod="updateProfile" schema=userSchema doc=currentUser collection=Users}}
{{> afQuickField name="profile.name.first" autofocus='' formgroup-class="col-xs-6"}}
{{> afQuickField name="profile.name.last" formgroup-class="col-xs-6"}}
{{/autoForm}}
I have checked your schema
Schema is looking good but you will have add object for the name.
Schema.UserProfile = new SimpleSchema({
'name': {
type: Object,
optional: false
},
'name.first': {
type: String,
max: 50,
label: "First name"
},
'name.last': {
type: String,
optional: true,
max: 50,
label: "Last name"
}
});

Cannot read property 'blackbox' of undefined - AutoForm and Meteor

Here's my schema:
TestCollection = new Meteor.Collection('test_collection');
var Schemas = {};
Schemas.TestCollection = new SimpleSchema({
servicesSelected: {
type: [Object]
},
"servicesSelected.0.selected" : {
type: Boolean,
optional: false
},
"servicesSelected.0.sku" : {
type: String,
optional: true
},
"servicesSelected.0.title" : {
type: String,
optional: true
},
"servicesSelected.0.price": {
type: Number,
optional: true
},
"servicesSelected.1.selected" : {
type: Boolean,
optional: false
},
"servicesSelected.1.sku" : {
type: String,
optional: true
},
"servicesSelected.1.title" : {
type: String,
optional: true
},
"servicesSelected.1.price": {
type: Number,
optional: true
}
});
TestCollection.attachSchema(Schemas.TestCollection);
My Template:
<template name="test">
{{#autoForm validation="keyup" collection="TestCollection" id="order-submission-test-form" type="insert"}}
<h1>Doing everything manually and specifying the data-schema-key:</h1>
<input type="checkbox" name="servicesSelected.0.selected" data-schema-key="servicesSelected.0.selected">
<label>HDR Photos</label>
<input type="checkbox" name="servicesSelected.1.selected" data-schema-key="servicesSelected.1.selected">
<label>Panos</label>
{{/autoForm}}
</template>
Whenever I click on the checkbox or try to validate the form I get a Cannot read property 'blackbox' of undefined error in the console. What am I doing wrong?
servicesSelected is supposed to be an array that contains hash tables on each index.
So something like:
serviceSelected = [
{
selected: true,
sku: "123",
title: "title1",
price: 100
},
{
selected: false,
sku: "124",
title: "title2",
price: 150
}
]
Just had the same issue, I would try getting rid of all numbers within your sub-object definitions. So I would try doing "servicesSelected.$.selected" instead of "servicesSelected.0.selected".
Worked for me, hopefully it works for anyone else with this strange issue.

Resources