How to validate input when submit without refreshing the page in Laravel? - ajax

if I have a unique column it will send a validate notif that indicates that this email already exists When I submit my input. I want to implement it in Laravel. Please, help me to start with this. Thanks

I am using axios for the example but you can you use jQuery Ajax as well
axios.post('/login', loginParams).then(function (r) {
//Do in case of success
}).catch(function () {
new Noty({
type: 'Danger',
text: '<b>' + r.data.success.name + '</b>',
}).show();
});
And in laravel
public function validator(Request $request)
{
$this->validate($request, [
'email' => 'required|email|max:255|unique:users',
]);
}

Related

Cannot catch error in promise chaining Larave-vue2 SPA authentication

I try to authenticate in Laravel9 Sanctum a SPA using vue3 and vuex, not with the token authentification but with the SPA Authentication.
I am not very used to the javascript language, and even less to promise chaining.
The first thing I am trying is registration.
Here are my methods.
The backend registration method
public function register(Request $request)
{
$request->validate([
'name' => 'required|string',
'email' => 'required|email|string|unique:users,email',
'password' => [
'required',
'confirmed',
Password::min(8)->mixedCase()->numbers()->symbols()
]
]);
$user=User::create([
'name' => $request['name'],
'email' => $request['email'],
'password' => bcrypt($request['password'])
]);
return response (['user'=>$user]);
}
The frontend registration method in the register.vue
//is actually the register form's data
const user = {
name: "",
email: "",
password: "",
password_confirmation: "",
};
function register(ev) {
ev.preventDefault();
store
.dispatch("register", user)
.then((data) => {
console.log("data in vue");
console.log(data);
router.push({
name: "Login",
});
})
.catch((error) => {
if (error.response.status === 422) {
errors = error.response.data.errors;
}
});
}
the actions method in the store/index.js
actions: {
register({ commit }, form) {
console.log("in register of index");
axiosClient.get("/sanctum/csrf-cookie");
return axiosClient.post("/api/register", form).then(({ data }) => {
console.log("data dans index");
console.log(data);
return data;
});
},
...
The registration is working fine but when I try an already existing email in the registration form, I get a status 422 as expected and this response from the axiosClient.post('/api/register',form):
{"message":"The email has already been
taken.","errors":{"email":["The email has already been taken."]}}
I expect this error to be intercepted by the catch in the register view but it doesn't happen. Despite this error I continue to use the .then and to push the Login route which is not what I want.
Can somebody tell me where I am doing wrong ?
I completely forget that in my axios.js there were interceptors that triggered this wrong behavior.
All is clear now.

Laravel API call goes through even with session expired

I have a SPA based on Laravel 5.8 and Vue 2.0.
Everything is working fine, a little bit too much to be honest, because if I delete the session and I try to save the content afterward or keep navigating the private pages, every ajax call that I'm doing with Axios is going through without returning any error. Only if I forcefully refresh the page I get the error page I setup but if I don't, I can keep doing everything even if the session no longer exist.
This is my setup.
web.php is where I have the only php route that points to a singlePageController:
Auth::routes();
Route::get('/{any}', 'SinglePageController#index')->where('any', '.*');
Then in the singlePageController I return the view:
class SinglePageController extends Controller
{
public function index() {
return view('app', ['loggedUser' => auth()->user()]);
}
}
Then I have the api.php where I have the API routes. As you can see at the end I have the middleware to make it private. Just to make an example this is the one I use for updating the content:
Route::put('event/update/{slug}', 'EventController#update')->middleware('auth:api');
Then the related controller of that API route:
public function update(Request $request, $slug)
{
$event = Event::where('slug', $slug)->first();
$event->title = $request->input('title');
return new EventResource($event);
}
And in the end this is the Resource I use to define what and how the API data is going to be displayed:
public function toArray($request)
{
// return parent::toArray($request);
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'curator' => $this->curator,
'featured_image' => $this->featured_image,
'body' => $this->body,
'date' => $this->date
];
}
So this above is the flow I have. Then when I do an axios call to update the content, I'm doing something like:
axios({
method: 'PUT',
url: '/api/event/update/' + this.$route.params.slug + '?api_token=' + this.isLogged.apiToken,
data: dataToSave,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
})
.then((response) => {
this.getNotification('Success: The Event has been saved');
})
.catch((error) => {
this.getNotification('Error: Impossible saving the event');
console.log(error);
})
Thanks in advance for the help
In Laravel routes in api.php ignore the session data.
If you want to authenticate with session data you could move your api routes to web.php and you should see the results you expect.

LARAVEL & VUE: How can I get the API_TOKEN of the logged in user with an API request?

I have a SPA using VUE and LARAVEL 5.8
I have setup an API_TOKEN associated to the logged in user. Everything works fine right after the login. I get the API_TOKEN, I save it into a var and I send it together with the Axios request. In Laravel I have a middleware that is taking care of the token and comparing it with the one setup on the logged in user.
the problem though occur when session expires. Because I still can navigate the private pages and make API requests to save and delete content. This is possible I think because I still have the same API_TOKEN saved in the var and the middleware apparently doesn't get that the session is expired.
So I want to obtain the API_TOKEN every time I'm doing an Ajax, request so when the session expires, I won't get the token and therefore, I won't be able to complete the request.
This is my setup.
web.php is where I have the only php route that points to a singlePageController:
Auth::routes();
Route::get('/{any}', 'SinglePageController#index')->where('any', '.*');
Then in the singlePageController I return the view:
class SinglePageController extends Controller
{
public function index() {
return view('app', ['loggedUser' => auth()->user()]);
}
}
Then I have the api.php where I have the API routes. As you can see at the end I have the middleware to make it private. Just to make an example this is the one I use for updating the content:
Route::put('event/update/{slug}', 'EventController#update')->middleware('auth:api');
Then the related controller of that API route:
public function update(Request $request, $slug)
{
$event = Event::where('slug', $slug)->first();
$event->title = $request->input('title');
return new EventResource($event);
}
And in the end this is the Resource I use to define what and how the API data is going to be displayed:
public function toArray($request)
{
// return parent::toArray($request);
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'curator' => $this->curator,
'featured_image' => $this->featured_image,
'body' => $this->body,
'date' => $this->date
];
}
So this above is the flow I have. Then when I do an axios call to update the content, I'm doing something like:
axios({
method: 'PUT',
url: '/api/event/update/' + this.$route.params.slug + '?api_token=' + this.isLogged.apiToken,
data: dataToSave,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
})
.then((response) => {
this.getNotification('Success: The Event has been saved');
})
.catch((error) => {
this.getNotification('Error: Impossible saving the event');
console.log(error);
})
Do you know how to make it? or if there is a better way to accomplish that?
you and do like, your login method should like this.
public function login(Request $request)
{
if (Auth::attempt(['email' => $request['email'], 'password' => $request['password']])) {
$user = Auth::user();
$success = $user->createToken(config('app.name'))->accessToken;
return response()->json(["token" => $success, 'status' => 200]);
} else {
return response()->json(['message' => "Email or Password do not match"], 401);
}
}

Codeigniter form validation in AJAX form submission

please help me.
I've been working recently in Codeigniter form validation without using AJAX and working fine, i just need to add $form_error to each field and everything just put on there. So, i am not good in javascript and really confusing how to show the errors response to each input field because when i am using AJAX the only idea i have is putting the response in a selector like $(#error-info)
This is my work so far
in my controller
$this->_rules();
if($this->form_validation->run() == FALSE)
$msg = array(
'name' => form_error('name'),
'phone' => form_error('phone'),
'email' => form_error('email')
);
echo json_encode($msg);
and my ajax :
<script type="text/javascript">
$(document).ready(function() {
$('#frm').submit(function(){
$.post($('#frm').attr('action'), $('#frm').serialize(), function( data ) {
console.log(data);
}, 'json');
return false;
});
});
</script>
the response look like this
{"name":"<small class=\"text-danger\">The name field is required.<\/small>","phone":"<small class=\"text-danger\">The phone field is required.<\/small>","email":"<small class=\"text-danger\">The email field is required.<\/small>"}
Please give me a hint. What a possible ways to do this?
Something like this should work (haven't tested):
PHP
$msg = array(
'name' => form_error('name'),
'phone' => form_error('phone'),
'email' => form_error('email')
);
echo json_encode(array('status' => 'error', 'response' => $msg));
AJAX
We assume that the indexes of the $msg array matches an actual id e.g. id='email' so we can propagate the error messages after the field.
$(document).ready(function () {
$('#frm').submit(function () {
$.post($('#frm').attr('action'), $('#frm').serialize(), function (res) {
var data = JSON.parse(res);
if (data.status == 'error') {
$.each(data.response, function(item_id, item_error_msg) {
$('#'+item_id).after().html(item_error_msg);
});
} else {
alert(data.response);
}
}, 'json');
return false;
});
});

Laravel form validation in image upload with ajax

I am working in laravel 5. and using blade and ajax for upload image.
Every thing was working fine unless I inserted validation code in store function inside controller. Getting server error:
POST http://localhost:8000/imgC 500 (Internal Server Error)
I guess there is something wrong with url inside ajax or in routes, I am using Restfull Controller.
image.blade.php
{{Form::open(array('url' => 'imgC', 'method' => 'post','files'=>true, 'id'=>'upload_form'))}}
Title: {{Form::text('title')}}
Image: {{Form::file('image')}}
{{Form::submit('submit',['id' => 'btnAddProduct'])}}
{{Form::close()}}
ImageController.php:
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|max:255',
]);
if ($validator->fails()) {
return "error";
}
$destinationpath = public_path() . '/img/';
$image=$request->input('image');
$filename=$request->file('image')->getClientOriginalName();
$request->file('image')->move( $destinationpath,$filename );
$img= new Image;
$img->name= $request->input('title');
$img->picture_path=$filename;
$saveflag=$img->save();
if($saveflag){
return Response::json(['success' => $saveflag, 'file' => asset($destinationpath.$filename)]);
}
}
AJAX function:
$(document).ready(function() {
$('#upload_form').submit(function (event) {
event.preventDefault();
$.ajax({
url: '/imgC',
data: new FormData($(this)[0]),
type: "POST",
processData: false,
contentType: false
}).done(function (response) {
console.log(response);
$("#success").show();
setTimeout(function() { $("#success").hide(); }, 5000);
});
});
});
route.php:
Route::resource('imgC', 'ImageController');
What am I doing wrong here?
I looked into the server log files and figured it out.
There was error with validation after adding Use Validator; in Image controller, problem solved

Resources