如何在db中存储输入类型的可用选项:select menu,radiobutton和checkbox?

如何在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 Table design Here there is 4 tables

  1. Question table : it will store thr dteails of question (id, question, conference_id, etc ) not storing the field information (text, radio_tbn etc)

  2. 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

  3. Field_type table : this will store actual html input type names (id,name) like textbox, radio_btn,select, etc

  4. 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 )

Sample Data Sample data