I have a dynamic form inside another form with two nullable fields and one required field. I've created one submit button to submit all of the form together. I've tried to code the store data part, but I keep getting "Undefined array key 2" error when I try to submit with one of the empty fields like this:
The size field is required, and the rest (barcode and image) are nullable. Please ignore the required mark, as I haven't removed it from my code.
What I need to achieve is these cases:
The View:
<!--Another Form here-->
<div class="col-sm-3-5 col-xl-4-5">
<div class="product-size-wrapper">
<div class="form-group row justify-content-center product-size-row pb-3">
<div class="col-xl-3">
<label class="control-label">Size <span class="required">*</span></label>
<input type="text" placeholder="Pack Size" class="form-control form-control-modern" name="size[]" required />
</div>
<div class="col-xl-3">
<label class="control-label">Barcode <span class="required">*</span></label>
<input type="text" class="form-control form-control-modern" placeholder="Barcode" name="barcode[]" />
</div>
<div class="col-xl-6">
<a href="#" class="product-size-remove text-color-danger float-end">Remove</a>
<label class="control-label">Image</label>
<div class="fileupload fileupload-new" data-provides="fileupload">
<div class="input-append">
<div class="uneditable-input">
<span class="fileupload-preview"></span>
</div>
<span class="btn btn-default btn-file">
<span class="fileupload-exists">Change</span>
<span class="fileupload-new">Select file</span>
<input type="file" name="image[]" />
</span>
<a class="btn btn-default fileupload-exists" data-dismiss="fileupload">Remove</a>
</div>
</div>
</div>
</div>
</div>
<div class="row justify-content-center mt-4">
<div class="col-xl-9 text-end">
<a href="#" class="product-size-add-new btn btn-primary btn-px-4 btn-py-2">+ Add New</a>
</div>
</div>
</div>
<script>
$(document).on('click', '.product-size-add-new', function(e) {
e.preventDefault();
var html = '' +
'<div class="form-group row justify-content-center product-size-row pb-3">' +
'<div class="col-xl-3">' +
'<label class="control-label">Size <span class="required">*</span></label>' +
'<input type="text" placeholder="Pack Size" class="form-control form-control-modern" name="size[]" required/>' +
'</div>' +
'<div class="col-xl-3">' +
'<label class="control-label">Barcode <span class="required">*</span></label>' +
'<input type="text" placeholder="Barcode" class="form-control form-control-modern" name="barcode[]" />' +
'</div>' +
'<div class="col-xl-6">' +
'<a href="#" class="product-size-remove text-color-danger float-end">Remove</a>' +
'<label class="control-label">Image</label>' +
' <div class="fileupload fileupload-new" data-provides="fileupload">' +
'<div class="input-append">' +
'<div class="uneditable-input">' +
'<span class="fileupload-preview"></span>' +
'</div>' +
'<span class="btn btn-default btn-file">' +
'<span class="fileupload-exists">Change</span>' +
'<span class="fileupload-new">Select file</span>' +
'<input type="file" name="image[]" />' +
'</span>' +
'<a class="btn btn-default fileupload-exists" data-dismiss="fileupload">Remove</a>' +
'</div>' +
'</div>' +
'</div>' +
'</div>' +
'';
$('.product-size-wrapper').append(html);
});
//Product Pack - Remove
$(document).on('click', '.product-size-remove', function(e) {
e.preventDefault();
$(this).closest('.product-size-row').remove();
});
Controller
$count = count($request->size);
for ($i = 0; $i < $count; $i++) {
//submit product pack with barcode & image
if ($request->barcode[$i] !== "" && $request->image[$i] !== "") {
$fileNames = [];
foreach ($request->file('image') as $pack_image) {
$fileName = $pack_image->hashName();
$pack_image->storeAs('products', $fileName);
$fileNames[] = $fileName;
}
$sizes = ProductSize::create([
'product_id' => $products->id,
'size' => $request->size[$i],
'barcode' => $request->barcode[$i],
'image' => $fileNames[$i],
'created_by' => Auth::user()->id,
]);
}
//submit product pack with barcode
elseif ($request->barcode[$i] !== "" && $request->image[$i] == "") {
$sizes = ProductSize::create([
'product_id' => $products->id,
'size' => $request->size[$i],
'barcode' => $request->barcode[$i],
'created_by' => Auth::user()->id,
]);
}
//submit product pack with image
elseif ($request->barcode[$i] == "" && $request->image[$i] !== "") {
$fileNames = [];
foreach ($request->file('image') as $pack_image) {
$fileName = $pack_image->hashName();
$pack_image->storeAs('products', $fileName);
$fileNames[] = $fileName;
}
$sizes = ProductSize::create([
'product_id' => $products->id,
'size' => $request->size[$i],
'image' => $fileNames[$i],
'created_by' => Auth::user()->id,
]);
}
//submit product pack without barcode & image
elseif ($request->barcode[$i] == "" && $request->image[$i] == "") {
$sizes = ProductSize::create([
'product_id' => $products->id,
'size' => $request->size[$i],
'created_by' => Auth::user()->id,
]);
}
// dd($request->image);
}
Please help because I'm still a beginner. Thank you.
Your issue is how you check if the data is sent or not.
Checking with $request->barcode[$i] !== "" requires that $request->barcode[$i] exists so it can be compared to the value "" (empty string)
You need to check if the array key exists before checking its value like
if (
(isset($request->barcode[$i]) && $request->barcode[$i] !== "") &&
(isset($request->image[$i]) && $request->image[$i] !== "")
) {
}
When the first statement isset($request->barcode[$i]) returns false, the second one $request->barcode[$i] !== "" will not be run because it's an AND condition, so you are safe doing it like this.
Remark: if we did it in the opposite order like this $request->barcode[$i] !== "" && isset($request->barcode[$i]) it will trigger the error. The order is important.
Here is a simplified example of your code:
$count = count($request->size);
//This bit of code is run multiple times while doing the same thing every time
$fileNames = [];
foreach ($request->file('image') as $pack_image) {
$fileName = $pack_image->hashName();
$pack_image->storeAs('products', $fileName);
$fileNames[] = $fileName;
}
for ($i = 0; $i < $count; $i++) {
//You can prepare the data before calling ProductSize::create()
$product = [
'product_id' => $products->id,
'size' => $request->size[$i],
'created_by' => Auth::user()->id,
];
//now check for image and barcode separately and add them to the array if present
if (isset($request->barcode[$i]) && $request->barcode[$i] != '') {
$product['barcode'] = $request->barcode[$i];
}
if (isset($request->image[$i]) && $request->image[$i] != '' && isset($fileNames[$i])) {
$product['image'] = $fileNames[$i];
}
$sizes = ProductSize::create($product);
}
PS: I highly suggest to check the links @aynber shared, even if it does not specifically relate to your issue and since you are a beginner, you will learn a lot from it (the answer on that is perfect)