Reputation: 115
Learning Meteor, which is great, but I'm struggling a bit with "best practice".
For example, I'm building a small example quiz, which looks like:
Question : 1 + 1 = ? ---> Dropdown box [1, 2, 3]
Question : 1 + 0 = ? ---> Dropdown box [1, 2, 3]
Question : 1 - 1 = ? ---> Dropdown box [1, 2, 3]
Question : 2 + 1 = ? ---> Dropdown box [1, 2, 3]
Then, at the bottom is a Button that says "Score Me".
When that button is pressed, it should go through each question and put a little "Correct" or "Wrong" next to the dropdown box.
All of this looks something like:
<template name="questions">
<div class="jumbotron">
{{#each questions}}
<span class="lead">{{question}} </span>
<select class="answerDropDown">
{{#each answer}}
<option value={{this}}>{{this}}</option>
{{/each}}
</select>
<span id="correctornot">{{correctornot}}</span>
{{/each}}
</div>
</template>
I'm pulling the data from the DB using:
Questions = new Mongo.Collection("questions");
And everything is working fine. I've plugged in events and it reacts well, etc... etc...
What I can't do easily is see how to make correctornot work. Well... I say that, but what I mean is nothing really makes sense.
I would imagine when I got the data:
Template.questions.helpers({
questions: function() {
return Questions.find({});
}
I would want to add extra data to each question, but this isn't meant to be saved in the database.
I guess I'm just looking for the correct way to go about it. Even the answers aren't saved anywhere, so when I check to see if it's correct, I'm currently looking at Session variables that are changed on the dropdown select event.
Anyway, all advice welcome.
Cheers.
Upvotes: 0
Views: 67
Reputation: 4820
What you want is benefit from Blaze's reactivity without persisting information in your database. The answer? Reactive client-side values! They come in different form:
When evaluated in designated contexts (such as helpers or Tracker.autorun
), the code included in said context will be ran again every time the value in the reactive variable changes, hence, in the case of helpers, triggering changes in your template.
Session
Here, we will see the easier way to achieve this, using the built-in Session
object. Let's assume your questions
template is included in a template called form
which contains your submit button:
<template name="form">
{{> questions}}
<form id="form">
<input type="submit" value="Score me" />
</form>
</template>
First, we must set a submitted
session variable to false
when the form
template gets rendered.
Template.form.onRendered(function () {
Session.set('submitted', false);
});
Then, catch the form submission event, and instead of submitting, we're going to set our new submitted
reactive variable to true.
Template.form.events({
'submit #form': function (e, t) {
e.preventDefault();
// do some prior validation here if needed
Session.set('submitted', true);
}
});
Now, all we need to do is to check in a submitted
template helper whether submitted
is set to true
or false
. If it is true
, we then proceed to display the result of the correctornot
helper, which fetches the value selected in the dropdown and compares it to the correct answer for the question stored in the current data context (the each
loop). Assuming this answer is stored in a correctAnswer
property of your question:
Template.questions.helpers({
'questions': function() {
return Questions.find({});
},
'submitted': function () {
return Session.get('submitted');
},
'correctornot': function () {
var userResponse = $('#'+this._id+'.answerDropDown').val();
return (this.correctAnswer == userResponse);
}
});
And here is our slightly enhanced questions
template:
<template name="questions">
<div class="jumbotron">
{{#each questions}}
<span class="lead">{{question}} </span>
<select id="{{_id}}" class="answerDropDown">
{{#each answer}}
<option value={{this}}>{{this}}</option>
{{/each}}
</select>
{{#if submitted}}
<span id="correctornot">{{correctornot}}</span>
{{/if}}
{{/each}}
</div>
</template>
As you can see, with very little code, you can achieve a nice reactive behavior.
Session
with a pointless flag?Then, you can look into reactive variables. They're easy to implement once you have the logic in your mind. The little tricky part in your case is that you seem to use nested templates: the submit button triggering the reactive change and the questions list reacting to it are not in the same template. So you will need to navigate between template instances to access the submitted
reactive variable. Look at this answer for clues on this subject.
Upvotes: 3