I have a page for the user to create a question. For that, the user needs to introduce a title for the question and the type. To select the type there is a select menu:
<div class="form-group">
<label for="type">Field type</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>
<option value="file">FIle</option>
</select>
</div>
If the user selects the type select menu, checkbox or radio button he also needs to introduce the options for the field. So if the user selects a field type of select menu, checkbox or radio button it will appear 2 fields by default for the user to introduce the values for the options:
<div class="form-group" id="availableOptions">
<label for="inputName">Available Options</label>
<div class="option">
<input type="text" class="form-control col-md-8" name="questionOptions[]">
<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" name="questionOptions[]">
<input type="button" class="removeOption btn btn-outline-primary col-md-3" value="Remove Option"/>
</div>
</div>
Doubt: My doubt is about how to validate the questionOptions form fields, because if the user select checkbox, select menu or radio button the user should at least introduce the value for 1 option input, that is the options cannot be null/empty. So in the rules I have " 'questionOptions' => 'required'". But if the user dont introduce any value for any option it appears an error instead of the validation message:
SQLSTATE[23000]: Integrity constraint violation:
1048 Column 'value' cannot be null
(SQL: insert into `question_options`
(`question_id`, `value`, `updated_at`,
`created_at`) values (8, , 2018-08-15 23:14:08, 2018-08-15 23:14:08)).
Do you know where is the issue?
Method to store the question:
public function store(Request $request, $id)
{
$rules = [
'question' => 'required',
'type' => 'required|in:text,long_text,select_menu,radio_btn,file,checkbox',
'questionOptions' => 'required'
];
$customMessages = [
'question.required' => 'The field title is required.',
'type.required' => 'The field type is required.',
'type.in' => 'Please introduce a valid type.',
'questionOptions.required' => 'Please introduce the value at least for 1 option.',
];
$this->validate($request, $rules, $customMessages);
$congress= Congress::find($id);
$question = Question::create([
'congress_id' => $congress->id,
'question' => $request->question,
'type' => $request->type,
]);
if (in_array($request->type, Question::$typeHasOptions)) {
foreach ($request->input('questionOptions') as $questionOption) {
QuestionOption::create([
'question_id' => $question->id,
'value' => $questionOption
]);
}
}
Session::flash('success', 'Question created with success.');
return redirect()->back();
}
You could try to custom rule. like this..
write custom rule in provider
public function boot()
{
Validator::extend('check_empty', function ($attribute, $value, $parameters, $validator) {
//your code to check if the value is empty in your way condition
return check_array_empty_your_code($value)
});
//this is for custom message
Validator::replacer('dns_email', function ($message, $attribute, $rule, $parameters) {
return "Please introduce the value at least for 1 option.";
});
}
then make request class
class StoreRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'question' => 'required',
'type' => 'required|in:text,long_text,select_menu,radio_btn,file,checkbox',
'questionOptions' => 'required|check_empty'
]
}
public function messages()
{
return [
'question.required' => 'The field title is required.',
'type.required' => 'The field type is required.',
'type.in' => 'Please introduce a valid type.',
'questionOptions.required' => 'Value is required',
];
}
}
Then use the request class in controller
public function store(StoreRequest $request, $id)
{
$congress= Congress::find($id);
$question = Question::create([
'congress_id' => $congress->id,
'question' => $request->question,
'type' => $request->type,
]);
if (in_array($request->type, Question::$typeHasOptions)) {
if (isset($request->questionOptions)) {
foreach ($request->questionOptions as $questionOption) {
QuestionOption::create([
'question_id' => $question->id,
'value' => $questionOption
]);
}
} else {
//return error
}
}
Session::flash('success', 'Question created with success.');
return redirect()->back();
}
To validate form fields expecting an array as value like is the case of questionOptions[]
, you can follow this approach in your validation rules and custom messages:
$rules = [
'question' => 'required',
'type' => 'required|in:text,long_text,select_menu,radio_btn,file,checkbox',
'questionOptions' => 'required|array',
'questionOptions.*' => 'filled'
];
$customMessages = [
'question.required' => 'The field title is required.',
'type.required' => 'The field type is required.',
'type.in' => 'Please introduce a valid type.',
'questionOptions.required' => 'Please introduce the value at least for 1 option.',
'questionOptions.array' => 'Please introduce the value at least for 1 option.',
'questionOptions.*.filled' => 'Please introduce the value at least for 1 option.'
];