Is there any way to specify the options helper in the schema? I tried:
Schema
{
favoriteColor: {
type: String,
autoform: {
options: "colorOptions"
}
}
}
But it does not seem to work.
The following technique works fine to display a select with options in a form:
Schema
{
favoriteColor: {
type: String
}
}
Helper
Template.myFormTemplate.helpers({
colorOptions: function () {
return Colors.find().map(function (c) {
return {label: c.name, value: c._id};
});
}
});
Template
{{> afQuickField name="favoriteColor" options=colorOptions}}
In my actual schema I have an array of objects, and in each object I need to select an item from different collection. When you use afArrayField you can no longer set the options in the template as I did in the Template above (because it's an array of objects, and one element in the object would refer the helper).
Is my only option to query the database when I define the scheme? That I guess would make it non reactive, right?
{
favoriteColor: {
type: String,
autoform: {
options: function () {
return Colors.find().map(function (c) {
return {label: c.name, value: c._id};
});
}
}
}
}
Inserting the helper function directly into the schema will work. I'm doing something similar and it is reactive.
Related
I'm trying to insert an array into an object and I'm not having any luck. I think the schema is rejecting it based on validation but I'm not sure why. If I console.log(this.state.typeOfWork) and check typeof it states its an Object which contains:
(2) ["Audit - internal", "Audit - external"]
0: "Audit - internal"
1: "Audit - external"
My collection after an update contains:
"roleAndSkills": {
"typeOfWork": []
}
Example: Schema
roleAndSkills: { type: Object, optional: true },
'roleAndSkills.typeOfWork': { type: Array, optional: true },
'roleAndSkills.typeOfWork.$': { type: String, optional: true }
Example: update
ProfileCandidate.update(this.state.profileCandidateCollectionId, {
$set: {
roleAndSkills: {
typeOfWork: [this.state.typeOfWork]
}
}
});
Simple schema has some problems with validation on Objects or Arrays, i had the same problem in a recent app i developed.
What can you do?
well, what i did, on the Collections.js file, when you are saying:
typeOfWork:{
type: Array
}
Try adding the property blackbox:true, like this:
typeOfWork:{
blackbox: true,
type: Array
}
This will tell your Schema that this field is taking an Array, but ignore further validation.
The validation i made was on main.js, just to be sure i had no empty array and the data was plain text.
As requested here is my update method, im my case i used objects not arrays but it works the same way.
editUser: function (editedUserVars, uid) {
console.log(uid);
return Utilizadores.update(
{_id: uid},
{$set:{
username: editedUserVars.username,
usernim: editedUserVars.usernim,
userrank: {short: editedUserVars.userrank.short,
long: editedUserVars.userrank.long},
userspec: {short: editedUserVars.userspec.short,
long: editedUserVars.userspec.long},
usertype: editedUserVars.usertype}},
{upsert: true})
},
here it the collection schema
UtilizadoresSchema = new SimpleSchema({
username:{
type: String
},
usernim:{
type: String
},
userrank:{
blackbox: true,
type: Object
},
userspec:{
blackbox: true,
type: Object
},
usertype:{
type: String
}
});
Utilizadores.attachSchema(UtilizadoresSchema);
Hope it helps
Rob
typeOfWork is an Array. You should push your value in it :
$push: {
"roleAndSkills.typeOfWork": this.state.typeOfWork
}
for multiple values :
$push: {
"roleAndSkills.typeOfWork": { $each: [ "val1", "val2" ] }
}
mongo $push operator
mongo dot notation
You state that this.state.typeOfWork is an array (of strings) but then when you .update() your document you are enclosing it in square brackets:
ProfileCandidate.update(this.state.profileCandidateCollectionId, {
$set: {
roleAndSkills: {
typeOfWork: [this.state.typeOfWork]
}
}
});
Simply remove the redundant square brackets:
ProfileCandidate.update(this.state.profileCandidateCollectionId, {
$set: {
roleAndSkills: {
typeOfWork: this.state.typeOfWork
}
}
});
Also since your array is just an array of strings you can simplify your schema a bit by declaring it as such with [String] for the type:
'roleAndSkills.typeOfWork': { type: [String] }
Note furthermore that objects and arrays are by default optional so you can even omit the optional flag.
Using SimpleSchema in Meteor with the AutoForm + Select2 plugins , i am trying to generate the Options for a Select field from the database.
The 'occupation' collection is published, and a collection 'Occupation' is defined in Meteor.
In SimpleSchema I have this:-
occupations: {
type: [String],
optional:true,
label: 'Occupation',
autoform:{
type:"select2",
placeholder: 'Comma spaced list of occupations',
options: function () {
Meteor.subscribe('occupations');
return Occupations.find({});
}
}
},
But it does not return the collection results, and crashes the application without an error message.
It seems the best way to handle this is to supply the options list through a helper.
{{> afQuickField name='occupations' multiple=true tags=true options=listOccupations}}
Where listOccupations is a helper within the template containing the form.
Template.myForm.helpers({
listOccupations: function () {
Meteor.subscribe('occupations');
return Occupations.find({}).fetch();
}
});
And we remove the options object from the schena
occupations: {
type: [String],
optional:true,
label: 'Occupation',
autoform:{
type:"select2",
placeholder: 'Comma spaced list of occupations',
}
},
Have you tried, this approach:
autoform: {
options: {
var occupations = [];
Occupations.find().map(function(occ) {
occupations.push(
{label: occ.description, value: occ._id}
);
});
return occupations;
}
}
hope this helps..
I had the same issue. I'm defining my collections schema in /lib/collections folder, and that is running on both server and client side. Given that, the console.log that I had was printing the correct values on server side and an empty array on client side.
What I did was:
if (Meteor.isClient){
Meteor.subscribe('service-categories-list', {
onReady: function(){
const serviceCategories = ServiceCategories.find({}).map(function(item, index) {
return {
label: item.name,
value: item.slug
};
});
Schema2._schema.type.autoform.options = serviceCategories;
}
})
}
I know that using the _schema is not a good idea, but I accept suggestions :)
I have global variable that store the url of the uploaded image by the user.
how do i add that variable as an attribute in the document before adding it to the database?
here is my code
Meteor.methods({
submitPost: function (app) {
// Console.log('new App:', app);
check(app, {
title: String,
description: String,
category: String,
price: Number
});
Products.insert(app);
}
});
i want to add the global variable inside "app" before inserting it in Products collection
How do i do it?
This is what i added in the collection
previewImage: {
type: String,
autoValue: function(){
return PIurl;
},
autoform: {
type: "hidden"
}
},
createdAt:{
type: String,
autoValue: function(){
return new Date();
},
autoform: {
type: "hidden"
}
}
}));
after i added the above code, nothing happens when i click on submit, the form is no longer stored in the database
Two ways you can achieve this, the first is to use AutoForm.hooks onSubmit hook autoform hooks. The other way is to add it to your schema with the object attribute of autoValue :
Schema.something = new SimpleSchema({
category: {
type: String,
autoValue: function () {
return "foo";
}
},
I have an app in Meteor and the idea is that an admin user can add a document and assign it to one of its customers (customers are stored in the user collection). So I would like to present a dropdownbox with customers on the document insert view. The relevant code of the schema is below:
customer: {
type: [String],
label: "Customers",
allowedValues: function () {
return Meteor.users.find().map(function (user) {
return user._id
});
},
autoform: {
options: function () {
return Meteor.users.find({}).map(function(user) {
return {
value: user._id,
label: user.profile.name
}
})
}
},
optional: true
}
When I put a type: String (instead of [String]) it shows the current user only in a dropdownbox. If I use [String] (as it should be), the dropdownbox actually turns in a text box (it does not have the typical dropdown behaviour) with 3 fields (for all the users it found), yet it only shows the first one again but leaves placeholders for the other 2.
The view uses:
{{> afQuickField name='customer'}}
IMPORTANT: The account package, by default doest not publish the users collection. You will have to write a new publication method in your server and corresponding subscription in your client for this to work.
No read on..
Well.. This is a bit tricky. Look at the code below and edit your 'autoform' section accordingly.
autoform: {
options: function () {
var options = [];
Meteor.users.find().forEach(function (element) {
options.push({
label: element.profile.name, value: element._id
})
});
return options;
}
}
the required syntax for selection box 'options' is:
options:{[label,value],...}
The above code reads all the rows from the user collection, and pushes each row to an array called 'options' as an array.
Hope this helps or gives you some insights.
Please note that the above only works if your collection subscription/publication are proper.
Look at the following code to get a simple idea.
if (Meteor.isClient) {
Meteor.subscribe('allUsers')
}
if (Meteor.isServer) {
Meteor.publish('allUsers', function() {
return Meteor.users.find({}, {fields:{username:1,emails:1}})
})
}
I'm trying to create a field modifiedBy with type: Object (to Meteor users).
I see you can setup blackbox: true for a Custom Object, but if I want to setup to a specific Object say a Group (collection) field modifiedBy is the logged in user, any pointers/help is greatly appreciated.
Thanks
As far as I see it, you have two options:
Store user-ids there with type: String
Denormalize it as you proposed
Denormalize it as you proposed
To denormalize it you can do something like this inside your schema:
...
modifiedBy: {
type: object
}
'modifiedBy._id': {
type: String,
autoValue: function () {
return Meteor.userId()
}
}
'modifiedBy.username': {
type: String,
autoValue: function () {
return Meteor.user().username
}
}
...
As you pointed out, you'd want to update these properties when they change:
server-side
Meteor.users.find().observe({
changed: function (newDoc) {
var updateThese = SomeCollection.find({'modifiedBy.username': {$eq: newDoc._id}})
updateThese.forEach () {
SomeCollection.update(updateThis._id, {$set: {name: newDoc.profile.name}})
}
}
})
Store user-ids there with type: String
I'd recommend storing user-ids. It's cleaner but it doesn't perform as well as the other solution. Here's how you could do that:
...
modifiedBy: {
type: String
}
...
You could also easily write a Custom Validator for this. Now retrieving the Users is a bit more complicated. You could use a transform function to get the user objects.
SomeCollection = new Mongo.Collection('SomeCollection', {
transform: function (doc) {
doc.modifiedBy = Meteor.users.findOne(doc.modifiedBy)
return doc
}
})
But there's a catch: "Transforms are not applied for the callbacks of observeChanges or to cursors returned from publish functions."
This means that to retrieve the doc reactively you'll have to write an abstraction:
getSome = (function getSomeClosure (query) {
var allDep = new Tacker.Dependency
var allChanged = allDep.changed.bind(allDep)
SomeCollection.find(query).observe({
added: allChanged,
changed: allChanged,
removed: allChanged
})
return function getSome () {
allDep.depend()
return SomeCollection.find(query).fetch()
}
})