如何在db中存储输入类型的可用选项:select menu,radiobutton和checkbox?
I have a form for a user create custom questions. The user needs to introduce the question and also the type of field (text, long text, checkbox, select menu, radio button). If the user selects one of this types: checkbox, select menu or radio button the div "#availableOptions" appears for the user to write the options for the questions of that type.
My doubt is how to store in the database this options. For now the database has the questions table that is like below but and dont have in account the available options.
For example if the user is creating a custom question "Receive notifications?" and select the type of the question as checkbox, it will appear the #availableOptions div. And the user can write in the first option "Yes" and in the second option "No".
My doubt is how to store in the database that "Yes" and "No" options. Do you know how this can be achieved? And the same for when is a select_menu or radio_btn.
In the database in the questions table is like:
id question conference_id type
1 Whats your phone? 1 text
2 Receive notifications? 1 radio_btn
3 .............. 1 checkbox
4 .............. 1 long_txt
5 .............. 1 select_menu
...
Form for the user create the custom question:
<form method="post" class="clearfix" action="{{route('questions.store', ['conference_id' => $conference->id])}}" enctype="multipart/form-data">
{{csrf_field()}}
<div class="form-group">
<label for="question">Question</label>
<input type="text" class="form-control" name="question" id="question">
</div>
<div class="form-group">
<label for="type">Type of field</label>
<select class="form-control" name="type" id="customQuestionType">
<option value="text">Text</option>
<option value="long_text">Long Text</option>
<option value="checkbox">Checkbox</option>
<option value="radio_btn">Radio Button</option>
<option value="select_menu">Select menu</option>
</select>
</div>
<div>
<input type="submit" class="btn btn-primary" value="Store"/>
</div>
</form>
<div class="form-group" id="availableOptions">
<label for="inputName" class="text-heading h6 font-weight-semi-bold">Available options</label>
<div class="option d-flex justify-content-between">
<input type="text" class="form-control col-md-8">
<input type="button" class="removeOption btn btn-outline-primary col-md-3" value="Remove option"/>
</div>
<div class="option mt-3 d-flex justify-content-between">
<input type="text" class="form-control col-md-8">
<input type="button" class="removeOption btn btn-outline-primary col-md-3" value="Remove option"/>
</div>
</div>
<div class="form-group">
<input type="button" class="btn btn-outline-primary mt-3" id="addNewOption" value="Adicionar nova opção"/>
</div>
<div class="float-right">
<a href="{{route('questions.edit', ['id' => $conference->id])}}" class="btn btn-outline-primary mt-3">Voltar à pàgina anterior</a>
<input type="submit" class="btn btn-primary mt-3" value="Guardar"/>
</div>
Then I have some jQuery, when a option is selected, if is a "select_menu", "radio_btn", "checkbox" it appears a div for the user to
$('#addNewOption').hide();
$('#availableOptions').hide();
$('#customQuestionType').change(function(){
var selected_option = $('option:selected', this).val();
alert(selected_option);
if (selected_option == "select_menu" || selected_option == "radio_btn" || selected_option == "checkbox") {
$('#addNewOption').show();
$('#availableOptions').show();
$('#addNewOption').click(function() {
$('#availableOptions').append(
'<div class="option form-row mt-3 d-flex justify-content-between">' +
'<input type="text" class="form-control col-md-8">' +
'<button class="removeOption btn btn-outline-primary col-md-3">Remove Option</button>' +
'</div>');
});
}else{
$('#availableOptions').hide();
}
});
QuestionController store() method:
public function store(Request $request, $id){
$this->validate($request, [
'question' => 'required|max:255|string',
'type' => 'required|max:255|string',
]);
$conference = Conference::find($id);
Question::create([
'conference_id' => $conference->id,
'question' => $request->question,
'type' => $request->type,
]);
Session::flash('success', 'Question created with success.');
return redirect()->back();
}
Question model:
class Question extends Model
{
public function registration_type(){
return $this->belongsToMany('App\TicketType', 'ticket_type_questions')->withPivot('required');
}
}
You can create a question_options
table that looks like this:
id | question_id | value
Create a relationship on the Question
model as follows:
public function options() {
return $this->hasMany(QuestionOption::class);
}
And the inverse on the QuestionOption
model
public function question() {
return $this->belongsTo(Question::class);
}
In your form name the input
fields for the options questionOptions[]
This will allow you to send the options in an array
Then in your store method you will have to do the following:
$question = Question::create([
'conference_id' => $conference->id,
'question' => $request->question,
'type' => $request->type,
]);
if($request->type == 'radio_btn') {
foreach($request->input('questionOptions') as $questionOption) {
QuestionOption::create([
'question_id' => $question->id,
'value' => $questionOption
]);
}
}
Now when you need to get the options you can simply check if the Question
type is radio_btn
and get the options via the relationship
It might be useful to add this to your Question
model:
public function hasOptions() {
return $this->type == 'radio_btn';
}
And then you can easily check if a Question
has options and show them (for example):
if($question->hasOptions()) {
foreach($question->options as $option) {
<p>{{ $option->value }}</p>
}
}
-- edit --
To make it easier to see which Question
type has options you can add this to the Question
model:
public static $typeHasOptions = [
'radio_btn',
'select_menu'
];
This will allow you to add more types that may have options in the future easily.
Then in your Controller method replace:
if($request->type == 'radio_btn') {
with:
if(in_array($request->type, Question::$typeHasOptions))
You can also update the hasOptions
method to be as follows:
public function hasOptions() {
return in_array($this->type, self::$typeHasOptions);
}
store in DB with a boolean for your value default value 0 => NO and get the value of your checkbox with
$(".yourcheckbox").change(function() {
if(this.checked) {
//Do the stuff
}
});
and just for your advice, you can refacto this
$('#addNewOption').click(function() {
$('#availableOptions').append(
'<div class="option form-row mt-3 d-flex justify-content-between">' +
'<input type="text" class="form-control col-md-8">' +
'<button class="removeOption btn btn-outline-primary col-md-3">Remove Option</button>' +
'</div>');
});
with a .trigger event of jquery here
or doing like this
var newString = [
'<div id="newDiv">',
'This is a new div',
'</div>'
].join('');
//New div created
$(newString).appendTo('.someClass');
//Append your new div to some class
hi @johnW can you try with this approach
Table Design
Here there is 4 tables
Question table : it will store thr dteails of question (id, question, conference_id, etc ) not storing the field information (text, radio_tbn etc)
Question_fields table : this will store the input type related to the question (id, question_id(fk), field_type_id (fk), value , text ) here value and text optional it will useful for radio button and check box
Field_type table : this will store actual html input type names (id,name) like textbox, radio_btn,select, etc
Select_options : this table is used to store the select box options (if you are adding the select potion in a json format with question_fields table you can remove this table )