So i am trying to update a user from the admin panel, i get the values from the form through a v-model and then i do my axios.put with all the data in a FormData(). The issue is that i get an error 500 saying that x field can't be empty, so i guess my FormData() isn't being passed on to the controller.
I tried with a post method and it worked fine. So i wonder what i did wrong ?
Here's the Vuejs code :
<script>
export default {
data () {
return {
search: '',
headers: [
{ text: 'ID', align: 'start', value: 'id'},
{ text: 'Name', value: 'name' },
{ text: 'Profile', value: 'profile' },
{ text: 'Email', value: 'email' },
{ text: 'Created At', value: 'created_at' },
{ text: 'Actions', value: 'actions' },
],
users: null,
editedUser: null,
dialog: false,
}
},
methods: {
getUsers(){
axios.get('../admin/getUsers')
.then(response => this.users = response.data)
},
editUser(item){
this.editedUser = item;
this.dialog = true;
},
submitEditedUser(){
let data = new FormData();
data.append('id', this.editedUser.id)
data.append('name', this.editedUser.name)
data.append('profile', this.editedUser.profile)
data.append('email', this.editedUser.email)
axios.put('../admin/updateUser/' + this.editedUser.id, data)
.then(res => {
console.log('done');
})
.catch(err => {
console.log('changes failed');
})
}
},
mounted(){
this.getUsers();
}
}
</script>
And here's the controller code :
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function updateUser($id, Request $request)
{
$user = User::find($id);
$user->name = request('name');
$user->profile = request('profile');
$user->email = request("email");
$user->save();
}
Everything works fine with post so nothing's wrong with the variable or the form, i think it really is just the data that's not being passed on. Although i want to use the put method because it is originally used for updating data.
Thanks !
can you try this? if this not work you can dd(request) inside the controller and see if is empty
public function updateUser($id, Request $request)
{
$user = User::find($id);
$user->name = $request->data['name'];
$user->profile = $request->data['profile'];
$user->email = $request->data['email'];
$user->save();
}
Related
With Axios I get a form created with Symfony FormBuilder, which I then display in a modal:
template.html.twig:
productId = {{product.id}};
var url = Routing.generate("stripe_admin_product_update_form", {id: productId});
axios.get(url)
.then(function(response){
var form = response.data.form;
Swal.fire({
title: "Modifier ?",
html: form,
icon: "question",
showCancelButton: true,
allowOutsideClick: () => !Swal.isLoading(),
preConfirm: function(result)
{
//submit form
}
});
});
controller.php
/**
* #Route("/admin/stripe/product/{id}/update/form", name="stripe_admin_product_update_form", options={"expose"=true})
*
*/
public function getUpdateProductForm(StripeProduct $product)
{
$form = $this->createFormBuilder($product)
->add("name")
->add("unitLabel")
->add("bankStatementLabel")
->getForm();
// if($form->isSubmitted() && $form->isValid())
// {
// Traitment
// }
$response = [
"code" => 200,
"form" => $this->render("stripe_admin/product/_form_edit.html.twig", [
"form" => $form->createView(),
])->getContent()
];
return new JsonResponse($response);
}
It gives me something like:
How can I now validate the form with Axios?
The goal is therefore to return to the function, and that the line :
if($form->isSubmitted() && $form->isValid())
be detected, so that I can handle any errors and do the rest of the processing
You have to handle the request like a classic form submission (understand not submitted with AJAX)
/**
* #Route("/admin/stripe/product/{id}/update/form", name="stripe_admin_product_update_form", options={"expose"=true})
*
*/
public function getUpdateProductForm(Request $request, StripeProduct $product)
{
$form = $this->createFormBuilder($product)
->add("name")
->add("unitLabel")
->add("bankStatementLabel")
->getForm();
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid())
{
//Traitment
}
$response = [
"code" => 200,
"form" => $this->render("stripe_admin/product/_form_edit.html.twig", [
"form" => $form->createView(),
])->getContent()
];
return new JsonResponse($response);
}
i created a form using AJAX because i have several alternatives concerning the fields.
I have correct information in my javascript and make tests... my first select use the following function and generates form
function setParentSector() {
$("#listSectors").html("");
$("#createSector").html("");
if($('#langname option:selected').val() !=0) {
var obj = { 'id': $('#langname option:selected').val() };
if (obj['id'] != 1) {
ajaxSectors(obj);
}
else
{
// another form generated here ...
$('#createSector').append("something else");
}
}
};
I use a "classical" ajax ..
function ajaxSectors(objSetParent) {
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: '/admin/ajax/sectorParent',
type: 'post',
dataType: 'json',
async: true,
success: function (result) {
$('#listSectors').append("<label for='langname'>label </label> " +
"<select class='form-control m-input m-input--air' id='sectors' onclick='setLangTranslation()'>" +
"<option value='0' selected>Select value</option></select>" +
"<span class='m-form__help' id='existsAlready'>");
var count = result.length;
for (var i = 0; i < count; i++) {
if (result[i].deleted_at === null) {
$('#sectors').append("<option value='" + result[i].sector_id + "'>" + result[i].sectname + "</option>");
}
else {
console.log("peanuts");
}
}
},
data:objSetParent,
error: function (result) {
},
complete: function (result) {
//console.log("complete");
}
});
}
This part of code works fine and i display what i want...
When I want to save into DB the form, I plan to use the store method and I create the $request->validate()
In the store method I have :
$request->validate([
'admin' => 'required',
'langname' => 'required',
'sectname' => 'required',
'sectshortname' => 'nullable',
]);
return view ('test')
The test view contains just in order to see what i post ..
If i keep the validate part, the page is just refreshed and not validated...
Without the request validate I display the view and i just see the value of the input with the token.
Thanks for your answers. Let's hope my question is "clear" enough
Use this code I hope this code works for you please use this Use Validator;
$rules = [
'admin' => 'required',
'langname' => 'required',
'sectname' => 'required',
'sectshortname' => 'nullable',
];
$data = $request->all();//or you can get it by one by one
$validator = Validator::make($data , $rules);
if ($validator->fails()) {
$error=[];
$errors = $validator->messages();
foreach($errors->all() as $error_msg){
$error[]= $error_msg;
}
return response()->json(compact('error'),401);
}
return view ('test')
I'm building my first API and I have this nightmare scenario where I see myself defining the same request data in multiples places. How are people maintaining their key/value payloads?
Here's my VueJS component on the client side:
<script>
export default {
data() {
return {
name: '',
description: '',
selectedHeader: '',
}
},
computed: {
businessUrl() {
return this.name.replace(/[^A-Z0-9]+/ig, '') + '.test.com';
},
},
methods: {
preview() {
let data = {
'name': this.businessUrl,
'description' : this.description,
'selectedHeader': this.selectedHeader
};
axios.post('/builder/preview', data)
...
</script>
Server-side:
public function preview()
{
$validatedData = request()->validate([
'name' => 'required',
'description' => 'string',
'selectedHeader' => 'required',
]);
$business = new Business;
$business->name = request('name');
$business->description = request('description');
$business->header = request('selectedHeader');
return view('business', compact('business'));
}
If I want to change the 'name' field that is posted on my route I have to do it in up to 5 places if I include references in my HTML. Any patterns that people have developed to avoid this duplication?
i want to post ajax request using vue-resource this.$http.post request. it worked perfectly fine if i passed all validation rules but i want to get some validations if it fails. so far i keep getting 500 error if i don't fill out some input fields. it's hard for me to debug the error because it didn't appeared on the network tab.
here's what i've done so far
//my modal component
<script>
export default {
props: ['show'],
data() {
return {
input: {
id: '',
name: '',
address: '',
email: ''
},
errorInputs: {}
}
},
methods: {
createStudent() {
this.$http.post('/students', this.$data.input)
.then((response) => {
alert('added new row!)
}, (response) => {
console.log(response.data);
});
}
}
}
</script>
// my controller
public function store(Request $request) {
$validator = $this->validate($request,[
'id' => 'required',
'name' => 'required|unique:students',
'email' => 'required|unique:students|email',
'address' => 'required',
]);
if($validator->passes()){
Student::create($request->all());
return response()->json([], 201);
}
$errors = json_decode($validator->errors());
return response()->json([
'success' => false,
'message' => $errors
],422);
}
any helps and references would be appreciated. i am using laravel 5.3 and vue js 2
$this->validate() returns 422 error response alongside your validation errors, so you should get those errors in then() second callback (like you do now). Your vue component body should be like this:
{
data() {
// ...
},
createStudent() {
this.$http
.post('/students', this.input)
.then(this.handleSuccess, this.handleError)
},
handleSuccess(res) {
alert('student created')
},
handleError(res) {
if (res.status === 422) {
this.errorInputs = res.body
} else {
alert('Unkown error!')
}
}
}
Remember to add v-model="input.fieldName" properties to your inputs.
Remember to include your session token along with your post, unless of course you are disabling csrf tokens for that route.
Since Laravel 5.1 you can disable this in your verifytoken middleware
<?php namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as ...
class VerifyCsrfToken extends ... {
protected $except = [
'payment/*',
];
}
Hi I'm having a problem outputting my json information on saving method in the model. I get the following error -
UnexpectedValueException in Response.php line 397:
The Response content must be a string or object implementing __toString(), "boolean" given.
I do validation on the model while saving and in the validate method of the model I need to out put the json but I'm getting boolean instead of json object
Javascript:
submit: function(e) {
e.preventDefault();
var contact = this.model.save({
firstname: this.firstname.val(),
lastname: this.lastname.val(),
company: this.company.val(),
email_address: this.email_address.val(),
description: this.description.val(),
}, {success:function(response){ console.log(response)}, wait: true});
Contact Model:
class Contact extends Model
{
protected $table = "contacts";
protected $fillable = ['firstname', 'lastname', 'company', 'email_address', 'description'];
public static function boot() {
parent::boot();
static::creating(function($model) {
return $model->validate('POST');
});
static::updating(function($model) {
return $model->validate('PUT');
});
static::saving(function($model) {
return $model->validate('PUT');
});
}
public function rules($method)
{
switch($method)
{
case 'GET':
case 'DELETE':
{
return [];
}
case 'POST':
{
return [
'firstname' => 'required',
'lastname' => 'required',
'email_address' => 'required|email|unique:contacts,email_address',
'description' => 'requried'
];
}
case 'PUT':
case 'PATCH':
{
return [
'firstname' => 'required',
'lastname' => 'required',
'email_address' => 'required|email|unique:contacts,email_address,'.$this->id,
'description' => 'required',
];
}
default: break;
}
return [];
}
public function messages() {
return [
'firstname.required' => 'Please enter your first name.',
'lastname.required' => 'Please enter your first name.',
'email_address.required' => 'Please enter a email address.',
'email_address.email' => 'Please enter a valid email address',
'email_address.unique' => 'The email is not unique.',
'description' => 'Please enter a description.'
];
}
public function validate($method)
{
$data = $this->attributes;
// if( $data['slug'] === '') {
// // if the slug is blank, create one from title data
// $data['slug'] = str_slug( $data['title'], '-' );
// }
// make a new validator object
$v = Validator::make($data, $this->rules($method), $this->messages());
// check for failure
if ($v->fails())
{
// set errors and return false
// json here not return response it's always boolean true or false
return new JsonResponse(array('error' => true, 'errors' => $v->messages()));
}
// validation pass
return true; //new JsonResponse(array('errors'=>false));
}
public function errors() {
return $this->errors;
}
public function user() {
return $this->hasOne('App\User', 'email', 'email_address');
}
}
Saving the model:
public function update(Request $request, $id) {
$contact = Contact::find($id)->with('user')->first();
$contact->firstname = $request->get('firstname');
$contact->lastname = $request->get('lastname');
$contact->email_address = $request->get('email_address');
$contact->company = $request->get('company');
$contact->description = $request->get('description');
return $contact->save(); //return formatted json
}
According to your implementation of validation, you should change the following part (in Contact):
// check for failure
if ($v->fails())
{
// set errors and return false
// json here not return response it's always boolean true or false
return new JsonResponse(array('error' => true, 'errors' => $v->messages()));
}
To something like this:
if ($v->fails()) {
$this->errors = $v->errors();
return false;
}
Then, from the Controller, try something like this:
// If validation failed
if(!$contact->save()) {
return response()->json([
'error' => true,
'errors' => $contact->errors()
]);
}
// Contact created if reached here...
return response()->json(['error' => false, 'contact' => $contact]);
Also, check the Ajax-Request-Validation and Form-Request-Validation (Easier and Managable).
Note: Don't try to return any kind of HTTP Response from model. Returning the HTTP response is part of your application logic and model should not care about these.
As save() does return boolean so You've to check if it's ok.
1) Change Your Contact model to put errors to model's errors param:
/* if($v->fails()) remove/comment this line
...
} */
$this->errors = $v->errors();
return !$v->fails();
2) In Your controller put this code:
public function update(Request $request, $id) {
$contact = Contact::find($id)->with('user')->first();
if(!$contact) {
return response('Contact not found', 404);
}
$contact->firstname = $request->get('firstname');
$contact->lastname = $request->get('lastname');
$contact->email_address = $request->get('email_address');
$contact->company = $request->get('company');
$contact->description = $request->get('description');
return $contact->save()?
$contact->toJson() : // returns 200 OK status with contact (json)
response($contact->errors, 400); // returns proper 400 Bad Request header with errors (json) in it
}
p.s. it's nice to answer to requester with http status, industry has made all to make life of developer easy, so if it's not 2xx, 3xx status so => response for Your request from client-side app will be treated as error (handler success: function(response) will not catch error here)