I am making a quiz web app. I have a class called an "answerBox", which currently just contains a button, an ID, and a Boolean. I want to call a "check Answer" function that determines if my answer is correct or not.
I assign the onclick to an anonymous function, and I send that function an object that is the same as the answerBox, but the onclick handler is not changing my answerBox object. It appears that it is creating a local copy. The code is here:
//currently just boilerplate checkAnswer function. Eventually will involve server calls. It is the client-side
//controller
function checkAnswer(ansBox)
{
console.log(ansBox.IDString);
if(ansBox.IDString == "Hello")
{
console.log("BEFORE: " + ansBox.IDString);
ansBox.IDString = "Goodbye";
console.log("AFTER: " + ansBox.IDString);
return true;
}
else
{
ansBox.IDString = "Hello";
return false;
}
}
class answerBox{
constructor(IDString){
this.IDString = IDString;
this.isCorrect = false;
//to register the onclick, we need a reference to this, which we can't have unless we
//create it, since the button's "this" is not the same as the answerBox's "this", hence, "that".
var that = this;
this.checkButton = m("button",{onclick: function(){that.isCorrect = checkAnswer(that); console.log(that.isCorrect)}},"Check" + this.IDString + " " + this.isCorrect);
}
view()
{
return this.checkButton;
}
}
I have an answerBox variable mounted to root using Mithril and it shows up just fine in the webpage. When I look at the console after clicking the button on the webpage, I get:
Hello
BEFORE: Hello
AFTER: Goodbye
true
Now, two things happen:
What am I doing wrong?
There's a couple of problems with the way you've written your component:
First of all, the constructor is written to accept a single argument, IDString
- but all Mithril component methods (including the constructor) receive a vnode
object, containing attrs
and children
which are passed in via hyperscript when the component is invoked. So assuming you would invoke your component as follows:
m(answerBox, {IDString: 'answerBox1'})
...then you would write the component to receive the IDString
in the constructor as follows:
class answerBox {
constructor(vnode){
this.IDString = vnode.attrs.IDString;
The next problem is that an answerBox
view will never change after instantiation, because its contents is only computed once, in the constructor, when this.checkButton
is defined. Rather than evaluating the view and assigning it to a property only to invoke that property, simply write it in the view function directly. The component then becomes:
class answerBox {
constructor(vnode){
this.IDString = vnode.attrs.IDString;
this.isCorrect = false;
}
view(){
var that = this;
return m("button", {
onclick: function(){
that.isCorrect = checkAnswer(that);
console.log(that.isCorrect)
}
},
"Check" + this.IDString + " " + this.isCorrect
);
}
}