Reputation: 529
Ok so I am making a "buzzfeed" quiz generator and I am having an issue with a piece of my form. So for each question made there are two different parts, a "Question" and the "Answers". There will always be 4 answers but I want to keep track of which Answers are checked later so I would like to give each answer a unique id "question" + questionNum + "Answer" + answerNum
or "question" + questionNum + "Answer" + i
So I made this answersGenerator
function that is supposed to give me 4 unique answer choice fill ins for the user to input answers for that specific questions (right now it says something about terms and conditions - ignore that I ad just left it like that for now because I was following a tutorial). Here is all my code:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import logo from './logo.svg';
import './App.css';
var questionNum = 1;
var answerNum = 1;
class App extends Component {
constructor(props) {
super(props);
this.state = {
quizTitle: "",
author: "",
question: "",
terms: false,
test: "",
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSubmit(event) {
event.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="App">
<div>
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
<div className="container">
<div className="columns">
<div className="formDiv">
<form className="form" onSubmit={this.handleSubmit}>
<div className="field">
<label className="label">Give your quiz a title.</label>
<div className="control">
<input
className="input"
type="text"
name="quizTitle"
value={this.state.quizTitle}
onChange={this.handleChange}
/>
</div>
</div>
<div className="field">
<label className="label">Who's the Author?</label>
<div className="control">
<input
className="input"
type="text"
name="author"
value={this.state.author}
onChange={this.handleChange}
/>
</div>
</div>
<div className="questions" id="questions">
<div className="question" id={'questionGroup' + questionNum}>
<div className="field">
<label className="label" id={'question' + questionNum}>Question {questionNum}</label>
<div className="control">
<input
className="input"
type="text"
name='question'
value={this.state.question}
onChange={this.handleChange}
/>
</div>
</div>
<div className="answersDiv">
<label className="label">Answers</label>
<div className="field">
<div className="control">
<label className="checkbox">
{this.answersGenerator()}
</label>
</div>
</div>
</div>
</div>
</div>
<div className="field">
<div className="endButtons">
<button id="addQuestionButton"
onClick={addQuestion}>Add Question</button>
<input
type="submit"
value="Submit"
id="submitButton"
className="button is-primary"
/>
</div>
</div>
</form>
</div>
<div className="column is-3">
<pre>
<code>
<p>Quiz Title: {this.state.quizTitle}</p>
<p>Author: {this.state.author}</p>
<p>Question: {this.state.question}</p>
<p>Terms and Condition: {this.state.terms}</p>
<p>Do you test?: {this.state.test}</p>
</code>
</pre>
</div>
</div>
</div>
</div>
);
}
}
function answersGenerator () {
console.log("hello this is answer generator");
var div = document.createElement('div');
div.className = 'answers' + {questionNum};
for (var i = 1; i < 5; i++){
div.innerHTML =
'<div className="field">\
<div className="control">\
<label className="checkbox">\
<label className="label">Answers</label>\
<input\
name="terms"\
type="checkbox"\
id="question'+{questionNum}+'Answer'+{i}+'"\
checked={this.state.terms}\
onChange={this.handleChange}\
/>\
I agree to the{" "}\
<a href="https://google.com">terms and conditions</a>\
</label>\
</div>';
document.getElementsByClassName('answersDiv')[0].appendChild(div)
}
}
function addQuestion () {
questionNum++;
console.log(questionNum + "that is the question number");
var div = document.createElement('div');
div.className = "questions" + questionNum;
div.innerHTML =
'<div id="questionGroup'+{questionNum}+'">\
Question '+{questionNum}+'<br />\
<input type="text" name="question'+{questionNum}+'"/><br />\
Answers<br />\
Check the box(es) for the correct answer(s).<br />\
<input type="checkbox" name="question'+{questionNum}+'Answer1Box" />\
<label for="question'+{questionNum}+'Answer1"><input type="text" name="question'+{questionNum}+'Answer1"/></label><br />\
<input type="checkbox" name="question'+{questionNum}+'Answer2Box" id= />\
<label for="question'+{questionNum}+'Answer2"><input type="text" name="question'+{questionNum}+'Answer2"/></label><br />\
<input type="checkbox" name="question'+{questionNum}+'Answer3Box" />\
<label for="question'+{questionNum}+'Answer3"><input type="text" name="question'+{questionNum}+'Answer3"/></label><br />\
<input type="checkbox" name="question'+{questionNum}+'Answer4Box" />\
<label for="question'+{questionNum}+'Answer4"><input type="text" name="question'+{questionNum}+'Answer4"/></label><br />\
</div>';
document.getElementsByClassName('questions')[0].appendChild(div)
}
export default App;
There's a few things to just ignore in here, i just wasn't sure how much info you needed. So the issue is that I get an error when I call my answersGenerator
function in my render
function. Here's the error Uncaught TypeError: this.answersGenerator is not a function
Here's the small piece where that is
<div className="answersDiv">
<label className="label">Answers</label>
<div className="field">
<div className="control">
<label className="checkbox">
{this.answersGenerator()}
</label>
</div>
</div>
</div>
I appreciate the help, if you have any other tips for me other than this issue I am having I am all ears. I am very new at this, being js and React.
UPDATE: I have edited the answersDiv
to be just this (I relized it was being called inside a checkbox)
<div className="answersDiv">
<label className="label">Answers</label>
{answersGenerator()}
</div>
I am still getting the same errors though.
Upvotes: 1
Views: 8394
Reputation: 3403
You're receiving the error because the answersGenerator()
isn't a method of your class App
, so, you can't refer to it using this
. If you want to do on that way, move you function to inside the component, like this:
class App extends Component {
// your component definition etc..
answersGenerator = () => {
// your function implementation
}
// the rest of your component
}
TIP:
If you dont want to have to always bind the function, like:
this.handleChange = this.handleChange.bind(this);
Declare your method like:
handleChange = (event) => { // the implementation }
Instead of
handleChange(event) { // the implementation }
The () => {}
, known as arrow function
, does the bind for your.
EDIT
You're developing with React, that supports creating HTML
inside your code. So, you can create an array of answers, then, return a div
with the answers mapped inside. The map
will take each answer
and render inside the div
. Try to define your method as below:
answersGenerator => () {
console.log("hello this is answer generator");
var answers = []
for (var i = 1; i < 5; i++){
answers.push(
<div className="field">
<div className="control">
<label className="checkbox">
<label className="label">Answers</label>
<input
name="terms"
type="checkbox"
id=`question${questionNum}Answer${i}`
checked={this.state.terms}
onChange={this.handleChange}
/>
I agree to the{" "}
<a href="https://google.com">terms and conditions</a>
</label>
</div>
);
}
return <div className=`answer${questionNum}`> {answers.map(answer => answer)} </div>
}
Upvotes: 1
Reputation: 17269
At first glance it looks like you haven't defined your answersGenerator()
function within your App
class.
Thus, this.answersGenerator()
doesn't exist.
Try just using answersGenerator()
without the this
.
Upvotes: 0