I'm having trouble adding new nested/array values to a collection using autoForm.
I'm trying to use a quickForm to update questions. I'd like the user to be able to add more answer options. My schema looks like this (simplified to omit order, some metadata, etc):
questionSchema = new SimpleSchema({
label: {
type: String
},
answers: {
type: Array,
minCount: 2,
maxCount: 6
},
"answers.$": {
type: Object
},
"answers.$._id": {
type: String,
regEx: SimpleSchema.RegEx.Id,
autoValue: function(){ return Random.id(); },
autoform: {
type: "hidden"
}
},
"answers.$.label": {
type: String,
regEx: /.{1,150}/,
autoform: {
label: false
}
},
"answers.$.count": {
type: Number,
defaultValue: 0,
autoform: {
type: "hidden"
}
}
});
Other than answers.$.label
, I was not using any autoform
options when I was just adding questions via a quickForm type='insert'
. I added those options when I wanted to edit questions because otherwise I got a complaint that I'd left count
null. So I made them hidden but let them be in the form.
My edit form looks like this:
{{> quickForm collection="Questions" id="editQuestionForm"
type="update" setArrayItems="true" doc=questionToEdit
fields="label, answers"}}
I'm currently able to update the labels for my question and any answers that I initially added. But I can't add new answer options. When I do that, it's denied because count
is not optional. But I specified a defaultValue
...
I would rather my quickForm look like this so that I'm not putting the count
s or _id
s where the user could change them:
{{> quickForm collection="Questions" id="editQuestionForm"
type="update" setArrayItems="true" doc=questionToEdit
fields="label, answers, answers.$.label"}}
But maybe I need to keep answers.$._id
there and hidden to ensure my changes update the right answers?
So:
My answer counts default to 0 on insert, so why doesn't that happen when I edit and add answers?
Can autoForm do an upsert instead of an update? Insert new questions, update existing question labels, use defaultalue
or autoValue
as needed.
Should I use a method for this type of thing?
EDIT: I've updated the example and deployed the test app to metoer at http://test-questions.meteor.com/. Its a bit rough around the edges (to be honest, it's anything but useful) but it should show the functionality in action. Use the add a new question link at the bottom. The existing questions should show up at the bottom of addquestion form. Click an existing question to edit it. Overall, the functionality is there. Just don't hate me for bad design. Blame the goddess of time.
The way I usually do embedded docs is by dividing each sub object into a separate schema. This keeps the code tidy and easier to understand as well as to avoid typical pitfalls.
Here a sample project demonstrating the below shema in action. Just git pull and meteor run: https://github.com/nanlab/question
new link http://app-bj9coxfk.meteorpad.com/
Code: http://meteorpad.com/pad/7fAH5RCrSdwTiugmc/
question.js:
Questions = new Mongo.Collection("questions");
SimpleSchema.answerSchema = new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
autoValue: function() {
return Random.id();
},
autoform: {
type: "hidden"
}
},
label: {
type: String,
regEx: /.{1,150}/,
autoform: {
label: false
}
},
count: {
type: Number,
autoValue: function() {
return 0;
},
}
})
Questions.attachSchema(new SimpleSchema({
label: {
type: String
},
answers: {
type: [SimpleSchema.answerSchema],
minCount: 2,
maxCount: 6
},
}))
Questions.allow({
insert: function(){return true;},
update: function(){return true;},
})
if(Meteor.isServer) {
Meteor.publish("questions", function() {
return Questions.find();
})
} else {
Meteor.subscribe("questions");
}