How to handle error from controller using PJAX in YII2? - javascript

I am using Yii2 Pjax widget which is unable to throw error from controller due to which I am unable to log error for users when there is any error coming from the controller.
PJAX code
<?php Pjax::begin([
'id' => 'createBucketPjax',
'timeout' => 4000,
'formSelector' => '#createBucketForm',
'enablePushState' => false,
'clientOptions' => [
'skipOuterContainers' => true,
'error' => new JsExpression("function(event) {
alert('Anything');
}"),
]
]); ?>
CONTROLLER code:
if(!$fieldModel->save()){
$transaction->rollBack();
//Here I want to send error
$error = $fieldModel->getErrorsString();
return [
'success' => false,'error' => $error
];
}else{
return $this->renderAjax('create', [
'model' => $model
]);
}
I have tried below clientOptions but not working
'error' => new JsExpression("function(event) {
alert('Please work');
}"),
Also used javascript but no help :-
$(document).on('pjax:error', function(event) {
console.log(event);
})
Is there any way from which I can send 404 from controller in yii2 ? That can actually resolve my problem

From the Yii2 Pjax docs.
In responding to the AJAX request, Pjax will send the updated body content (based on the AJAX request) to the client which will replace the old content with the new one. The browser's URL will then be updated using pushState. The whole process requires no reloading of the layout or resources (js, css)
You must deal with full form content and not with json.
So you code must look like following (always return the form html back):
if(!$model->save()){
$transaction->rollBack();
}
return $this->renderAjax('create', [
'model' => $model
]);

Related

All Put & Delete route method Throw 302 error in my laravel vue js project

I'm developing a laravel vue js application. Here I have a problem that all put & Delete method are throwing 302 error
this is my localhost response
this is my server response
Everything is running perfectly on my local pc but when I'm uploading this to the server then only get and post method working perfectly. Put & delete method throwing 302 error.
My route
Route::apiResource('category','CategoryController');
My Controller
public function update(Request $request, Category $category)
{
$this->validate($request, [
'name' => 'required',
]);
$category->name = $request->name;
$category->slug = Str::slug($request->name);
$category->save();
}
My Vue Component(I'm using V-form)
updateData() {
if (this.$middleware.admin()) {
this.$Progress.start();
this.form.put('api/category/' + this.form.id)
.then(() => {
Fire.$emit('getCategory');
$('#modal').modal('hide');
Toast.fire({
icon: 'success',
title: 'Category Updated successfully',
});
this.$Progress.finish();
})
.catch(() => {
this.$Progress.fail();
});
}
},
Try spoofing your method by adding <input type="hidden" name="_method" value="PUT"> to your form.
Or you could add _method: "PUT", to your component's form definition.
Take a look at the docs: https://laravel.com/docs/8.x/routing#form-method-spoofing

Create/update lead using Javascript for Intercom?

We would like to create/update a lead in Intercom via Javascript, we can do it through the PHP, but I have no idea how to do the same with Javascript, because we are using Unbounce landing page and when visitor fill out the form we would like send it to Intercom and create the lead for us.
We can use Zapier integration inside the Unbounce but passing the UTM parameters is not allowed, so we want to use the Intercom API/Javascript directly.
Below is the PHP script that we are using to create lead through WP Intercom API
Anyone how to do the same using Javascript? so I can put inside the Unbounce page script manager.
$client = new IntercomClient('xxxxxxxxxxxxx=', null);
try {
// First check if this already exists
$leads = $client->leads->getLeads(['email' => $post['email']]);
foreach ($leads->contacts as $lead) {
$id = $lead->id;
}
if(!$id) {
$id = '';
}
$client->leads->update([
"id" => $id,
"email" => $post['email'],
"name" => preg_replace("/[^a-zA-Z0-9\s]/", "", ucwords($post['first_name'])),
"last_request_at" => time(),
"last_seen_ip" => $_SERVER['REMOTE_ADDR'],
"utm_campaign" => $post['Utm_campaign],
"utm_content" => $post['Utm_content'],
"utm_medium" => $post['Utm_medium'],
"utm_source" => $post['Utm_source'],
"utm_term" => $post['Utm_term'],
'Form Message' => preg_replace("/[^a-zA-Z0-9\s]/", "", $post['description'])]
]);
} catch(ClientException $e) {
$response = $e->getResponse();
$statusCode = $response->getStatusCode();
if ($statusCode == '404') {
// Handle 404 error
return;
} else {
throw $e;
}
}

Unable to customize form errors because server is returning 422 Unprocessable Entity without returning errors

I'm working with Laravel and VueJS and for all of my post and put methods server returns the newly created data after submitting the form, in the case of errors, I cannot access them from the browser console. This is what I can see in the newtwork tab.The purpose is to customize form errors according to errors that is being returned by the server
Here is my backend code :
private function validateForm($data){
return Validator::make($data,
[
'fname' => ['required', 'string','min:2' ,'max:255'],
'lname' => ['required', 'string','min:2' ,'max:255'],
// 'mname' => ['string','min:2' ,'max:255'],
'company' => ['string','min:2' ,'max:255'],
'title' => ['string','min:2' ,'max:255'],
'phone_number' => ['string','min:13' ,'max:13'],
'city' => ['required', 'string','min:2' ,'max:100'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed']
// 'password_confirm'=>['required','string']
]
)->validate();
}
//Register
public function register(Request $request){
$data=$this->validateForm($request->all());
$data['password']=Hash::make($data['password']);
$user=new User($data);
$user->save();
return response()->json($user);
}
And my code from the front-end:
export default{
data(){
return {
form:{
email:'',
password:'',
password_confirmation:'',
fname:'',
lname:'',
city:''
},
formError:''
}
},
methods:{
//This should be a POST method through axios
register:async function(){
try{
const res=await axios.post('api/register',
{
email:this.form.email,
password:this.form.password,
password_confirmation:this.form.password_confirmation,
fname:this.form.fname,
lname:this.form.lname,
city:this.form.city
});
//Une fois inscrit,il est redirige vers la page de login
this.$router.push({path:'/login'});
console.log("My data : ",res.data);
}catch(err){
console.log("Errors",err);
}
}
}
}
When there are no errors, everything goes fine, but when there are errors, this is what I get in the browser console tab:
And in the Devtools network tab
I've tried the following link Issues with Axios catch method from Laracast
how to display the errors in .catch coming from an api on frontend
And some others solution,but all of them didn't solve my problem.
Before using async-await pattern i used axios.post('url',data).then(res=>...).catch(err=>...)
When i use postman,http status is still 422 but the error object is returned,so with postman everything goes fine but not in the browser
How can i solve this problem?
Laravel returns the HTTP 422 - Unprocessable Entity when the validations you set fail. In your case I would take a closer look at the data you're posting to the server and manually check if it passes the validation cases you wrote.
To get the exact fields that are causing the error you need to handle this in your code, like this for example:
$validator = Validator::make($data, $rules);
if ($validator->fails()) {
// 500 is the HTTP Status Code you want to return.
// This should also throw you in the catch branch of your front-end code
return response()->json(['errors'=>$validator->errors()], 500);
}
In your code the $data variable from the register function should be checked if it fails validation and return the error
This is because err will return the toString() method when accessed directly, but has properties:
err.response.data will have what you're looking for.
When there's an HTTP error (e.g. a response code between 400 and 599) axios returns an axios error response and in the repository documentation under error handling it indicates that you can access the actual response using error.response.data. For example:
try {
const res=await axios.post('api/register',
{
email:this.form.email,
password:this.form.password,
password_confirmation:this.form.password_confirmation,
fname:this.form.fname,
lname:this.form.lname,
city:this.form.city
});
//Une fois inscrit,il est redirige vers la page de login
this.$router.push({path:'/login'});
console.log("My data : ",res.data);
}catch(err){
if (err.response && err.response.status === 422) {
if (err.response.data.errors.fname) {
console.log('First name errors: '+ err.response.data.errors.fname.join(','));
}
// and so on
}
}
When Axios throws an error, the HTTP response can be found in error.response. Validation errors will be in the errors key, so you can access validation errors like this:
axios.post(someUrl, someData)
.then(response => {
// Successful response
})
.catch(error => {
let errors = error.response.data.errors;
});

Showing kartik growl via ajax in yii2

Am using kartik growl and i would like to show the growl via ajax success
I have tried
This is the javascript code:
$.post({
url: "forwardpr", // your controller action
dataType: 'json',
data: {keylist: keys,user:userdata},
success: function(data) {
console.log(data);
//$.pjax.reload({container:'#forward-grid'});
$.growl( data.growl );
},
error: function(err){
alert(err);
console.log("server error");
}
});
This is the controller code:
$growl = [
'title' => "Group members updated.<hr>",
'icon' => 'glyphicon glyphicon-ok-sign',
'message' => "Successifully updated.",
'showSeparator' => true,
];
echo json_encode(['response'=>"Successifully forwarded pr(s)", 'growl' => $growl ]);
If you see TypeError: $.growl is not a function, then it means you have not included required files to AppAsset.php file.
To solve this problem, go to assets/AppAsset.php file and add:
public $css = [
// ... Something else might be here
'css/jquery.growl.css',
];
And
public $js = [
// Something else might be here
'js/core.js',
];
Because of missing .js file, you have that error in console (TypeError: $.growl is not a function). But you also must add .css file as well because without it you will not see growl, even though it works.
I believe you're using the wrong function. Here's offical docs:
"Another important update is since version 3.x you no longer call the
plugin using $.growl(...) you must use $.notify(...)."
In another words, just try using $.notify(...) instead of $.growl(...).

Laravel 5 Validation - Return as json / ajax

I am trying to post the values into validation and return the response as json rather than return view as given in the documentation.
$validator = Validator::make($request->all(), [
'about' => 'min:1'
]);
if ($validator->fails()) {
return response()->json(['errors' => ?, 'status' => 400], 200);
}
The post is made by ajax so I need to receive the response in the ajax as well.
I figured out that in order to prevent refresh of the page in the returning response, I have to give it a status code of 200 outside the array. But I couldn't figure out what to give the 'errors' part. What should I write in there?
You can use $validator->messages() that returns an array which contains all the information about the validator, including errors. The json function takes the array and encodes it as a json string.
if ($validator->fails()) {
return response()->json($validator->messages(), Response::HTTP_BAD_REQUEST);
}
Note: In case of validation errors, It's better not to return response code 200. You can use other status codes like 400 or Response::HTTP_BAD_REQUEST
You can also tell Laravel you want a JSON response. Add this header to your request:
'Accept: application/json'
And Laravel will return a JSON response.
In Laravel 5.4 the validate() method can automatically detect if your request is an AJAX request, and send the validator response accordingly.
See the documentation here
If validation fails, a redirect response will be generated to send the user back to their previous location. The errors will also be flashed to the session so they are available for display. If the request was an AJAX request, a HTTP response with a 422 status code will be returned to the user including a JSON representation of the validation errors.
So you could simply do the following:
Validator::make($request->all(), [
'about' => 'min:1'
])->validate();
I use below this code for API in my existing project.
$validator = Validator::make($request->all(), [
'ride_id' => 'required',
'rider_rating' => 'required',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 400);
}
in case you are using a request class.
you may use failedValidation to handle you failed
/**
* Returns validations errors.
*
* #param Validator $validator
* #throws HttpResponseException
*/
protected function failedValidation(Validator $validator)
{
if ($this->wantsJson() || $this->ajax()) {
throw new HttpResponseException(response()->json($validator->errors(), 422));
}
parent::failedValidation($validator);
}
For those who have created a custom request class can override the public function response(array $errors) method and return a modified response without Validator explicitly.
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\JsonResponse;
class CustomRequest extends FormRequest
{
public function rules()
{
$rules = [
//custom rules
];
return $rules;
}
public function response(array $errors)
{
return new JsonResponse(['error' => $errors], 400);
}
}
My solution is to make my own FormRequest class which I put in the root API namespace namespace App\Http\Requests\Api.
Hope this helps someone
https://jamesmills.co.uk/2019/06/05/how-to-return-json-from-laravel-form-request-validation-errors/
Actually I used #Soura solution but with a little change. You need to import the Validator package as well.
$validator = \Validator::make($request->all(), [
'ride_id' => 'required',
'rider_rating' => 'required',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 400);
}

Categories

Resources