I am sending data from ionic project using api. And receiving from laravel. My "Add" product api is working fine. But "Update" product api is not working.
I can see from browser inspection tool that Request payload got data which is being send to laravel. So, data is being send but laravel is not able to real that data.
This is update function for api.
public function update(Request $request, Product $product)
{
// Validate request
$validatedData = $request->validate([
'account_type' => 'required|in:1,2',
'name' => 'required|string|max:255',
'description' => 'nullable|string',
'price' => 'required|numeric|min:0'
]);
// Update product
$product->update($validatedData);
return response()->json($product);
}
This is giving following error
account_type [ "The account type field is required." ]
name [ "The name field is required." ]
price [ "The price field is required." ]
and so on..
Laravel unable to read data for some reason.
Update
<form [formGroup]="productForm" (ngSubmit)="onSubmit()">
<!-- Add Type -->
<ion-item>
<ion-label>Add Type <span class="required">*</span></ion-label>
<ion-radio-group formControlName="account_type">
<ion-item>
<ion-label>Individual</ion-label>
<ion-radio slot="start" value="1"></ion-radio>
</ion-item>
<ion-item>
<ion-label>Business</ion-label>
<ion-radio slot="start" value="2"></ion-radio>
</ion-item>
</ion-radio-group>
</ion-item>
<!-- Ad Title -->
<ion-item>
<ion-label position="floating">Ad Title <span class="required">*</span></ion-label>
<ion-input formControlName="name" type="text"></ion-input>
</ion-item>
<!-- Submit Buttons -->
<div class="ion-padding">
<ion-button type="submit" expand="block" [disabled]="productForm.invalid">
{{ isEditMode ? 'Update Product' : 'Submit Now!' }}
</ion-button>
<ion-button expand="block" color="light">Preview</ion-button>
</div>
Didn't add all field of form here to make it short.
TS FILE
onSubmit() {
if (this.productForm.valid) {
const formData = new FormData();
const formValues = this.productForm.value;
// Append all form data
Object.keys(formValues).forEach((key) => {
if (key !== 'image' && key !== 'additionalImages') {
formData.append(key, formValues[key]);
}
});
// Handle file inputs
const mainImage = document.querySelector('[formControlName="image"]') as HTMLInputElement;
if (mainImage && mainImage.files && mainImage.files[0]) {
formData.append('image', mainImage.files[0]);
}
const additionalImages = document.querySelector('[formControlName="additionalImages"]') as HTMLInputElement;
if (additionalImages && additionalImages.files) {
Array.from(additionalImages.files).forEach((file) => {
formData.append('additionalImages[]', file);
});
}
// Differentiate between add and update
if (this.isEditMode) {
const productId = Number(this.route.snapshot.paramMap.get('productId'));
this.productService.updateProductPost(productId, formData).subscribe(
(response) => {
console.log('Product updated successfully:', response);
this.router.navigate(['/success']);
},
(error) => {
console.error('Error updating product:', error);
}
);
} else {
// Get the query string parameter
const categoryId = this.route.snapshot.paramMap.get('categoryId'); // Extract categoryId from query string
console.log('Category ID:', categoryId);
// Get the sessionStorage value
const userId = sessionStorage.getItem('userId'); // Extract userId from sessionStorage
// Append query string and sessionStorage data to the formData
if (categoryId) {
formData.append('category_id', Number(categoryId).toString());
}
if (userId) {
formData.append('seller_id', Number(userId).toString());
}
this.productService.addProduct(formData).subscribe(
(response) => {
console.log('Product added successfully:', response);
this.router.navigate(['/success']);
},
(error) => {
console.error('Error adding product:', error);
}
);
}
} else {
console.error('Form is invalid');
}
}
PRODUCT.SERVICE.TS
//Add product (is working)
addProduct(product: FormData): Observable<Product> {
return this.http.post<Product>(`${this.apiUrl}/products`, product);
}
//update producd
updateProductPost(productId: number, product: FormData): Observable<Product> {
return this.http.put<Product>(`${this.apiUrl}/products-update/${productId}`, product);
}
Laravel route in api.php
Route::put('products-update/{id}', [ProductApi::class, 'update']);
This is the case of incorrectly defined implicit model-binding
.
When you use implicit model-binding
you need to use the same name
for the Route parameter and for the injected model instance into the controller method(in your case update(Request $request, Product $product)
).
So change you route defination like this.
Route::put('products-update/{product}', [ProductApi::class, 'update']);
N:B :-
implicit model-binding
.