Cannot update data using vue.js in laravel - laravel

In my update form i have a file field that i want to update so i'm using following code and created a form object but when i pass form object i cannot get the data of form object in my controller.
let formData = new FormData();
formData.append('name', this.form.name);
formData.append('description', this.form.description);
formData.append('file_update', this.form.file_update);
axios.put(`/api/saveClass/${this.ItemId}`,formData,{headers:header})
.then((response)=>{
var msg = response.data.message;
if(response.status ==200){
this.$Progress.finish();
}else{
this.$Progress.fail();
}
this.$router.push(`/api/showClass`);
})
.catch(() => {
});
},
Laravel Controller:
public function update(Request $request,$id)
{
$ItemStore = class::find($id);
$this->validate($request,[
'name' => 'required|string|max:191|unique:class,name,'.$id,
'description' => 'required',
]);
}
I am getting name and description field is required but i'm passing data to it.

Related

How to avoid error "The PUT method is not supported for this route. Supported methods: GET, HEAD." using Laravel

I am using Laravel 7 and Vue.js 2.
When I edit a room I should update the rooms table and then to redirect to the admin page with a succesfull message.
Unfortunately when I submit the form I edit correctly the table but then the redirect fails. It appears the following error message:
message: "The PUT method is not supported for this route. Supported methods: GET, HEAD.
This is my two methods in AdminController:
public function index()
{
$permissions = Permission::select('id')->get();
$rooms = Room::all();
$languages = Language::all();
$users = UserResource::collection(User::all());
return view('admin')->with(['success_message' => '', 'permissions'=>$permissions, 'users'=>$users, 'rooms'=>$rooms, 'languages'=>$languages]);
}
public function edit_room (Request $request) {
$validator = Validator::make($request->all(), [
'id' => 'required',
'name' => 'required'
]);
if ($validator->fails()) {
return response($validator->errors());
}
$room = Room::find($request->id);
$room->name = $request->name;
$room->save();
$success_message = "The room " . $request->name . " has been correctly edited";
return Redirect::route('admin')->with( ['success_message' => $success_message] );
}
This is the axios call in my child component:
editRoom: function() {
axios.put('edit_room', { id: this.rooms[this.index].id, name: this.roomName })
.then((response) => {
console.log(response);
this.errors = response.data;
if (Object.keys(this.errors).length === 0) {
alert('viva');
this.user = {};
} else {
alert('noviva');
}
})
.catch(error => {
alert(noooooo);
console.log(error);
});
}
This is my two routes in web.php:
Route::put('edit_room', 'AdminController#edit_room')->name('edit_room');
Route::get('/admin', 'AdminController#index')->name('admin');
This is an update of the table so I suppose I should use a PUT method but for some reason it doesn't.
Which is the best way to solve this error?
I think the problem is that you send your request via XHR
So when you using
return Redirect::route('admin')->with( ['success_message' => $success_message]
it sends an response with 301 http code to redirect your browser
i think you should refactor your code like this for example
return 'success_message'
and then in your axios after console.log(response);
window.location.href = "http://www.your_address.com/admin";

How to store validator errors into an object with Laravel and Vue.js

I am using Laravel 7 and Vue.js 2.
I made a form that should show a table if every field has been inserted.
I made also a server-side validation to check if all fields are correctly inserted.
This is the function that creates a call to the server with Axios:
runReport: function() {
const url = "api/get_report?room="+this.formReport['room']+"&participant="+this.formReport['participant']+"&start="+this.formReport['start']+"&end="+this.formReport['end'];
axios.get(url)
.then((response) => {
console.log(response.data.data);
this.meetingsReport = response.data.data;
alert('viva');
this.$emit('passMeetings', this.meetingsReport);
this.$emit('success');
})
.catch(function(error) {
console.log(error.response.data);
this.errors = error.response.data; //problem
alert('noviva');
});
}
This is the validator in the controller:
$validator = Validator::make($request->all(), [
'room' => 'required',
'start' => 'required',
'end' => 'required',
'participant' => 'required',
]);
if ($validator->fails()) {
return response($validator->errors(), 422);
}
If everthing has been correctly inserted in the form I have no problems, but if I missed a field I am unable to store the errors in an empty object that I created called errors.
UPDATED: This is the response from the validation failed (status 422):
{
"room": [
"The room field is required."
],
"participant": [
"The participant field is required."
]
}
I suppose the problem is that I am unable to access to this.errors from the catch block of Axios.
this in the context of an anonymous function doesn't point to the vue instance, so you may need to bind this to the function or use arrow function within the catch block
.catch(error => {
console.log(error.response.data);
this.errors = error.response.data; //should not be any - problem
alert('noviva');
});
At the end I solved using the keyword self in the axios call. In this way I was able to connect the catch block with Vue.js component.
This is the code:
runReport: function() {
let self = this;
const url = "api/get_report?room="+this.formReport['room']+"&participant="+this.formReport['participant']+"&start="+this.formReport['start']+"&end="+this.formReport['end'];
axios.get(url)
.then((response) => {
console.log(response.data.data);
this.meetingsReport = response.data.data;
alert('viva');
this.$emit('passMeetings', this.meetingsReport);
this.$emit('success');
this.errors = {};
})
.catch(function(error) {
console.log(error.response.data);
self.errors = error.response.data;
self.$emit('failure');
});
}

Laravel controller validation of request with nested parameters

I am trying to validate in my controller a request of nested parameters but I can't get it working. I did find a few resources online and tried different things with no success.
This is the script that sends the data to the controller:
var fieldsValuePair = {
type: this.history.type
};
axios.get('/app/admin/cms/clients/processActivity', {
params: {
fieldsValuePair: fieldsValuePair,
hid: this.history.hid
}
})
.then((response) => {})
.catch(error => {
this.errors = [];
this.errors = error.response.data;
console.log(this.errors);
});
This is my validation in my controller:
$this->validate($request, ['type' => 'required'] , ['activity-type.required']);
I want to say that if i add: type: this.history.type in my axios request just after hid: this.history.hid then the validation works correctly.
What I want to achieve is to have the type: this.history.type in the fieldsValuePair object and have this validate correctly in the controller.
I did find a solution but not sure if this would be the best one. At least it's working for me.
$rulesArray = [];
$fieldsValuePairArray = json_decode($request['fieldsValuePair'], true);
foreach ($fieldsValuePairArray as $key => $value) {
if($value == '')
$rulesArray[$key] = 'required';
}
$this->validate($request, $rulesArray , ['activity-type.required']);

How To Submit Form If The User Don't Want To Add hasMany FormItems

I'm using Laravel 5.7.*.
I have form which hasMany formItems, Like a form hasMany formItems & formItems belongsTo form, but i want an if between them, that if user don't want to add formItems only form data store in DB and if user want to add formItems both data store in DB, right now, it's storing both data in DB, but i don't how to make it store if user don't want formItems.
Here is my FormController store method():
public function store(Request $request)
{
//SUBMITTING FORM DATA
$form = Form::create([
'user_phone' => $request['user_phone'],
'user_name' => $request['user_name'],
]);
//SUBMITTING FORMITEMS DATA
$form_items = [];
foreach($request['formItems'] as $form_item) {
$form_items[] = new FormItem([
'form_id' => $form->id,
'family_name' => $form_item ['family_name'],
'family_phone' => $form_item ['family_phone'],
]);
}
$form->formItems()->saveMany($form_items);
}
Image For Better Understanding:
you can do this
public function store(Request $request)
{
//SUBMITTING FORM DATA
$form = Form::create([
'user_phone' => $request['user_phone'],
'user_name' => $request['user_name'],
]);
$form_items = [];
foreach($request['formItems'] as $form_item) {
// when the user enter $form_item ['family_name'] && $form_item ['family_phone'] store the FormItem
// or $form_item ['family_name'] || $form_item ['family_phone']
// depending if both are required or not
if($form_item ['family_name'] && $form_item ['family_phone']){
$form_items[] = new FormItem([
'form_id' => $form->id,
'family_name' => $form_item ['family_name'],
'family_phone' => $form_item ['family_phone'],
]);
}
}
$form->formItems()->saveMany($form_items);
}
You could have a checkbox on your form to ask the user if they want to save form items too.
<input type="checkbox" name="save-form-items" value="true" id="save-form-items">
<label for="save-form-items"> Do you want to save form items?</label>
and then in your controller, you can do something like this:
public function store(Request $request)
{
//SUBMITTING FORM DATA
$form = Form::create([
'user_phone' => $request['user_phone'],
'user_name' => $request['user_name'],
]);
if ($request->has('save-form-items')) {
$form_items = [];
foreach($request['formItems'] as $form_item) {
$form_items[] = new FormItem([
'form_id' => $form->id,
'family_name' => $form_item ['family_name'],
'family_phone' => $form_item ['family_phone'],
]);
}
$form->formItems()->saveMany($form_items);
}
}

Laravel request validation - nullable image

I have registration form with username, email, password and avatar(image) fields. Everything works except image filed, which can be null. I am using Vue as front-end and send data with axios to Laravel.
This is validation:
public function register(Request $request)
{
$request->validate([
'username' => 'required|string|max:255|unique:users',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6',
'avatar' => 'nullable|image|mimes:jpg,jpeg,png|max:1999'
]);
$fileNameToStore = 'noimage.jpg';
return User::create([
'username' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->password),
'avatar' => $fileNameToStore
]);
}
And this is how I send data:
register(context, data) {
let formData = new FormData();
formData.append('avatar', data.avatar)
formData.append('username', data.username)
formData.append('email', data.email)
formData.append('password', data.password)
return new Promise((resolve, reject) => {
axios.post('/register', formData,{
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
resolve(response)
})
.catch(error => {
reject(error)
})
})
}
If I fill out every filed it works fine and also other things like checking extension or file size works, only problem is when I don't select any image. I have nullable included in validation, but I still get error message from validation that it must be an image and which extension it needs to have.
If your data.avatar is undefined or null, your server will eiter receive a undefined or null string as a value for your avatar field. Therefore, Laravel will be testing the image rule on the string.
To fix it, you can make sure your image is not undefined to send it in your request.
if (data.avatar) {
formData.append('avatar', data.avatar);
}
Or
formData.append('avatar', data.avatar ? data.avatar : '');
this is because of data.avatar send to backend as an empty string and
you can write a watch for data.avatar, which every time data.avatar is empty string change it to null . like the following code :
watch(){
'data.avatar'(value){
if(value == '' || value == undefined){
this.data.avatar = null
}
}
}
This is how I did mine and it worked for me very well, I just added a ref attribute on the input that should be the user avatar and then retrieved the value of the input through Vue as follows this.$refs.photo.files[0]:
In my HTML using Vue
<input id="image" class="opacity-0" type="file" ref="photo">
and in my js using Vue
var data = new formData();
if(this.$refs.photo.files.length > 0)
data.append('photo', this.$refs.photo.files[0]);
axios.post(...).then(...);

Resources