Input array inside json by ajax not working properly in laravel - laravel

I'm using Semantic UI and Laravel 6
I got this html code:
<div class="field">
<label for="realTime">Tiempo real</label>
<input type="text" id="realTime" name="schedules[{{ $service->id_service }}][realTime]" required/>
</div>
<div class="field">
<label for="delayTime">Tiempo de demora</label>
<input type="text" id="delayTime" name="schedules[{{ $service->id_service }}][delayTime]" required/>
</div>
<div class="field">
<label for="deathTime">Tiempo muerto</label>
<input type="text" id="deathTime" name="schedules[{{ $service->id_service }}][deathTime]" required/>
</div>
And I'm sending this info by ajax using this code:
$.ajax({
url: "...",
data: {
"formData": $(formClass).form('get values')
},
success: function (response) {
// skipped code
}
});
But when I dump the request data in controller using:
dd($request->input('formData'));
I got this result:
array:1 [
"formData" => array:1 [
"schedules[1" => array:3 [
"realTime" => "12:00:00"
"delayTime" => "13:00:00"
"deathTime" => "14:00:00"
]
]
]
Instead of:
array:1 [
"formData" => array:1 [
"schedules" => array:1 [
1 => array:3 [
"realTime" => "12:00:00"
"delayTime" => "13:00:00"
"deathTime" => "14:00:00"
]
]
]
]
I checked out the content sent shown in Headers tab (using Chrome) and I found this:
formData[schedules[1][realTime]]: 12:00:00
formData[schedules[1][delayTime]]: 13:00:00
formData[schedules[1][deathTime]]: 14:00:00
I also realized that if I put the name as "schedules][{{ $service->id_service }}][realTime]" (putting an extra closing bracket after "schedules"), the dump shows the array correctly.
Any solution?

Related

Multiple Checkbox with textbox enable/disable & array

I have multiple checkbox field and when any checkbox checked then 3 input field appear. I want to insert data for 1 checkbox value with 3 input value.
Form:
<div class="form-check">
<input class="form-check-input fighting_style" name="txt_fightingStyle[]" type="checkbox" value="MMA" id="MMA">
<label class="form-check-label" for="flexCheckDefault">
MMA
</label>
<section class="fighiting_value" id="MMA_input" style="display: none;">
<div class="row">
<div class="col-3">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-dark">WIN</label>
<input type="text" class="form-control fights txt_win"
name="txt_win[]" onblur="totalFights()" id="txt-win" placeholder="">
</div>
</div>
<div class="col-3">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-dark">LOSS </label>
<input type="text" class="form-control fights txt_loss" data-points = "75"
name="txt_loss[]" onblur="totalFights()" id="txt-loss" placeholder="">
</div>
</div>
<div class="col-3">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-dark">DRAW</label>
<input type="text" class="form-control fights txt_draw" data-points = "150"
name="txt_draw[]" onblur="totalFights()" id="txt-draw" placeholder="">
</div>
</div>
</div>
</section>
</div>
Javascript:
document.querySelectorAll("input[type=checkbox]").forEach(cb=>cb.addEventListener("click",ev=>{
let sibl=(cb.closest("label")??cb).nextElementSibling;
while(sibl&&!sibl.matches("section"))
sibl=sibl.nextElementSibling;
sibl.style.display=ev.target.checked?"":"none";
}));
document.querySelectorAll("input[type=text]").forEach(t=>t.addEventListener("blur",ev=>totalFights()));
This is my dd result
"txt_win" => array:12 [▼
0 => null
1 => null
2 => null
3 => "4"
4 => null
5 => "4"
6 => null
7 => null
8 => null
9 => null
10 => null
11 => null
]
"txt_loss" => array:12 [▼
0 => null
1 => null
2 => null
3 => "5"
4 => null
5 => "5"
6 => null
7 => null
8 => null
9 => null
10 => null
11 => null
]
"txt_draw" => array:12 [▼
0 => null
1 => null
2 => null
3 => "6"
4 => null
5 => "6"
6 => null
7 => null
8 => null
9 => null
10 => null
11 => null
]
my controller:
$dataWin = $request->txt_win;
$dataLoss = $request->txt_loss;
$dataDraw = $request->txt_draw;
foreach ($dataFightingStyle as $fightStyle) {
FighitData::create([
'fighting_style' => $fightStyle,
'winning_game' =>$dataWin,
'lost_game' => $dataLoss,
'draw_game' => $dataDraw,
]);
}
I just want to which checkbox box checked only when the check box is selected only the data of its text field can be taken and the rest will be disabled. Is there any way to do this.
I i understood your problem correctly, you need to get text fields related to checkboxes. In this case you could try something like that :
$dataWin = $request->txt_win;
$dataLoss = $request->txt_loss;
$dataDraw = $request->txt_draw;
foreach ($dataFightingStyle as $key => $fightStyle) {
FighitData::create([
'winning_game' =>$dataWin[$key],
'lost_game' => $dataLoss[$key],
'draw_game' => $dataDraw[$key],
]);
}

How to translate custom values for all indexes of array based form input fields for validation in Laravel

Take this array based form input fields that allows user to add and remove items with type (simple or complex) and complex infos:
<div class="item">
<div>
<h2>Type</h2>
<label><input type="radio" name="data[0][type]" value="simple"> Simple ABC stuff</label>
<label><input type="radio" name="data[0][type]" value="complex"> Complex XYZ stuff</label>
</div>
<div class="complex"> <!-- it will be visible only when type is "Complex XYZ stuff" -->
<h2>Complex info</h2>
<input type="text" name="data[0][complex_info]"/>
</div>
<button class="remove">Remove item</button>
</div>
<div class="item">
<div>
<h2>Type</h2>
<label><input type="radio" name="data[1][type]" value="simple"> Simple ABC stuff</label>
<label><input type="radio" name="data[1][type]" value="complex"> Complex XYZ stuff</label>
</div>
<div class="complex"> <!-- it will be visible only when type is "Complex XYZ stuff" -->
<h2>Complex info</h2>
<input type="text" name="data[1][complex_info]"/>
</div>
<button class="remove">Remove item</button>
</div>
<button class="add">Add item</button>
When user selects the "Complex XYZ stuff" type, then "Complex info" input should be required. So we set this form request rule in Laravel 6.x:
public function rules() {
return ['data.*.complex_info' => 'required_if:data.*.type,complex'];
}
When the required_if validation rule fails, we get the error message The :attribute field is required when :other is :value. that with the filled parameters should result in a message like this: The Complex info field is required when Type is Complex XYZ stuff. (expected message).
The following validation.php language file would work for a form of 2 items:
return [
/* ... */
'values' => [
'data' => [
0 => [
'type' => [
'simple' => 'Simple ABC stuff',
'complex' => 'Complex XYZ stuff',
]
],
1 => [
'type' => [
'simple' => 'Simple ABC stuff',
'complex' => 'Complex XYZ stuff',
]
],
]
]
];
And I need it to work for a form with an indefinite number of items (all indexes), so I thought about using the * wildcard like:
return [
/* ... */
'values' => [
'data' => [
'*' => [
'type' => [
'simple' => 'Simple ABC stuff',
'complex' => 'Complex XYZ stuff',
]
],
]
]
];
But it doesn't work, the :value parameter of the required_if validation rule's error message is not properly translated: The Complex info field is required when Type is complex. (actual message).

How to update a table record using laravel inertia and vue.js

I use Laravel 8 inertia and vue
I want to update a post and I use this component in a main vue
<template>
<div class="container p-3 bg-green-600 flex flex-col">
<div class="mb-8 text-2xl">{{ current_post.title }}</div>
<div v-if="!edit" id="mode-display">
<div v-html="compiledMarkdown" class="text-gray-700"></div>
</div>
<div v-else id="mode-edit">
<form class="flex flex-col" #submit.prevent="updatePost">
<input type="hidden" name="id" id="id" v-model="current_post.id">
<button type="submit">Mettre à jour</button>
<div class="flex">
<div class="m-5 flex flex-col">
<label for="category">Catégorie du post</label>
<select class="px-2" name="category" id="category" v-model="current_post.category">
<option value="undefined">Sans</option>
<option value="Announcements">Annonce</option>
<option value="Narratives">Récit</option>
<option value="Pages">Page</option>
</select>
</div>
<div class="m-5 flex flex-col">
<label for="diaporama_dir">Dossier du diaporama</label>
<input name="diaporama_dir" id="diaporama_dir" type="text" placeholder="admin|1/Noël2019" v-model="current_post.diaporama_dir">
</div>
</div>
<div class="flex">
<div class="m-5">
<label for="beg_date">Date de début de l'événement</label>
<date-picker name="beg_date" format="YYYY-MM-DD" valueType="format" v-model="current_post.beg_date"></date-picker>
</div>
<div class="m-5">
<label for="end_date">Date de fin de l'événement</label>
<date-picker name="end_date" format="YYYY-MM-DD" valueType="format" v-model="current_post.end_date"></date-picker>
</div>
<div class="m-5">
<label for="close_date">Date de clôture des inscriptions</label>
<date-picker name="close_date" format="YYYY-MM-DD" valueType="format" v-model="current_post.close_date"></date-picker>
</div>
<div class="m-5 flex flex-col">
<label for="receive_registration">Accepte des inscriptions</label>
<select class="px-2" name="receive_registration" id="receive_registration" v-model="current_post.receive_registration">
<option value="false">Non</option>
<option value="true">Oui</option>
</select>
</div>
</div>
<input class="p-5 mb-5 text-xl" type="text" v-model="current_post.title" />
<div class="m-5 flex flex-col">
<label for="abstract">Résumé</label>
<textarea class="markdown bg-green-500 text-gray-100" name="abstract" id="abstract" v-model="current_post.abstract" rows="3"></textarea>
</div>
<div class="m-5 flex flex-col">
<label for="body">Résumé</label>
<textarea class="markdown bg-green-500 text-gray-100" name="body" id="body" v-model="current_post.body" rows="50"></textarea>
</div>
</form>
</div>
</div>
</template>
<script>
import DatePicker from 'vue2-datepicker';
import 'vue2-datepicker/index.css';
import 'vue2-datepicker/locale/fr';
import marked from 'marked';
export default {
name: "PostDetails",
props: ["current_post", "edit"],
components: {
DatePicker
},
data() {
return {
form:{
id:null,
title: null,
abstract: null,
body: null,
category: null,
beg_date: null,
end_date: null,
close_date : null,
receive_registration : null,
diaporama_dir: null
}
};
},
methods:{
updatePost(){
this.$inertia.post('/post', this.form);
}
},
computed: {
compiledMarkdown: function () {
if (this.current_post) {
//transform markdown to html
return marked(this.current_post.body);
}
},
mounted() {},
}
};
</script>
When displaying this template with the form , I receive a correct post and its values are correctly displayed in the various input fields.
My controller, at the moment is very simple :
public function Update(Request $request)
{
dd($request);
}
On submitting this form the dd outputs this:
Illuminate\Http\Request {#43 ▼
#json: Symfony\Component\HttpFoundation\ParameterBag {#35 ▶}
#convertedFiles: null
#userResolver: Closure($guard = null) {#342 ▶}
#routeResolver: Closure() {#351 ▶}
+attributes: Symfony\Component\HttpFoundation\ParameterBag {#45 ▶}
+request: Symfony\Component\HttpFoundation\ParameterBag {#35 ▼
#parameters: array:10 [▼
"id" => null
"title" => null
"abstract" => null
"body" => null
"category" => null
"beg_date" => null
"end_date" => null
"close_date" => null
"receive_registration" => null
"diaporama_dir" => null
]
}
+query: Symfony\Component\HttpFoundation\InputBag {#51 ▶}
+server: Symfony\Component\HttpFoundation\ServerBag {#47 ▶}
+files: Symfony\Component\HttpFoundation\FileBag {#48 ▶}
+cookies: Symfony\Component\HttpFoundation\InputBag {#46 ▶}
+headers: Symfony\Component\HttpFoundation\HeaderBag {#49 ▶}
#content: "{"id":null,"title":null,"abstract":null,"body":null,"category":null,"beg_date":null,"end_date":null,"close_date":null,"receive_registration":null,"diaporama_dir ▶"
#languages: null
#charsets: null
#encodings: null
#acceptableContentTypes: null
#pathInfo: "/post"
#requestUri: "/post"
#baseUrl: ""
#basePath: null
#method: "POST"
#format: null
#session: Illuminate\Session\Store {#392 ▶}
#locale: null
#defaultLocale: "en"
-preferredFormat: null
-isHostValid: true
-isForwardedValid: true
-isSafeContentPreferred: null
basePath: ""
format: "html"
}
It seems to me I am obeying the guidance given in this page https://inertiajs.com/forms but why on earth the form's value are not uploaded to the server?
In your code, you're sending the form object (which is full of null values).
For now, you can fix it like this:
updatePost () {
this.$inertia.post('/post', this.current_post);
}
But probably you're having a vue-warn saying that it's not recommended to edit a prop.
so I suggest also the following:
you receive the post prop as current_post
you should copy it to your form object (on mounted)
link all of your form inputs to the form object instead of current_post
I can not add a comment yet but wanted to add that if You clone a reactive object You are not actually copying it. The cloned object is the same as the original and modifying this new object modifies the original object too and vice versa so basically You are doing exactly the same thing that got You in trouble at the first place: Modifying properties.
Vue states that You should not modify a property because if a parent component modifies a prop your changes are gone.
Lodash clonedeep creates a new object from the property:
this.items = _.cloneDeep(this.data);

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'score' cannot be null

Controller
public function getScore(Request $request, $id)
{
// $scores = Criteria::find($id);
$contestants = Contestant::find($id);
foreach ($request->criteria as $id => $criteria){
$criteriaModel = Score::find($id);
$scores = new Score();
$scores->judge_name = $request->input('judge_name');
$scores->contestant = $contestants->name;
$scores->criteria = $criteriaModel->criteria;
$scores->score = $scores->score;
$scores->save();
}
return redirect('/tabulation')->with('status', 'Score saved!');
}
Blade
#foreach ($criterias as $criteria)
<div class="form-group col-md-6">
<label for="{{$criteria->name}}">{{$criteria->name}} </br> (0 - {{$criteria->points}})</label>
<input type="text" name="criteria[{{$criteria->id}}][criteria]" value="{{$criteria->name}}" hidden>
<input type="text" name="score[{{$criteria->id}}][score]" class="form-control" placeholder="Input score" required>
</div>
#endforeach
Form field names can contain brackets to store multiple properties for a single name:
#foreach ($criterias as $criteria)
<div class="form-group col-md-6">
<label for="{{$criteria->name}}">{{$criteria->name}} </br> (0 - {{$criteria->points}})</label>
<input type="text" name="criterias[{{$criteria->id}}][name]" value="{{$criteria->name}}" hidden>
<input type="text" name="criterias[{{$criteria->id}}][points]" class="form-control" placeholder="Input score" max="{{$criteria->points}}" name="score" required>
</div>
#endforeach
The above form would result the $request->criterias variable containing the following value:
array:2 [▼
1 => array:2 [▼
"name" => "test"
"points" => "dd"
]
2 => array:2 [▼
"name" => "tes22t"
"points" => "sdsd"
]
]
This value can be used in the controller for creating multiple scores:
foreach ($request->criterias as $id => $criteria){
$criteriaModel = Criteria::find($id);
$scores = new Score();
$scores->judge_name = $request->input('judge_name');
$scores->contestant = $contestants->name;
$scores->criteria = $criteriaModel->name;
$scores->score = $criteria->points;
$scores->save();
}
First of all you have to change the name of your input to be an array like so:
<input type="text" name="criteria[]" value="{{$criterias->name}}" hidden>
and in your controller you have to loop through the inputs:
foreach ($request->input('criteria') as $criteria){
$scores = new Score();
$scores->judge_name = $request->input('judge_name');
$scores->contestant = $contestants->name;
$scores->criteria = $request->input('criteria');
$scores->score = $request->input('score');
$scores->save();
}

Laravel date before_equal is allowing all dates through

$DOB = $request->input('DOB');
$allowed = Carbon::now()->subYears(26)->format('Y-m-d');
$validatedData = $request->validate(
['DOB' => 'required|date|before_or_equal:'.$allowed],
);
<input type="date" name="DOB" class="form-control" required>
I am having a hard time validating dates in Laravel.
If I enter 01/01/2018 in the form, the validation does not catch it. Below it what is returned if I dd() the variables.
dd([$DOB, $allowed]);
array:2 [▼
0 => "2018-01-01"
1 => "1992-04-26"
]
No idea where I am going wrong.

Resources