I am working on Yii 1 application. In my application, there is a CGridView where there is a link, which also fires an ajax request on onclick event. I am sending id as parameter. But the ajax return 400 Bad Request error. Please help me in this matter.
Here is the Gridview:
<h3>Civil Cases</h3>
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'notifications-grid',
'dataProvider'=>$dataProvider_civil,
'summaryText' => false,
'columns'=>array(
array(
'name' => 'case_id',
'type' => 'raw',
'value' => 'CHtml::link(CHtml::encode($data->case_id),array("civilcases/view","id"=>$data->case_id), array("onclick"=>"js:readNotification($data->id)"))'
),
array(
'name' => 'caseno',
'type' => 'raw',
'value' => 'CHtml::link(CHtml::encode($data->caseno),array("civilcases/view","id"=>$data->case_id), array("onclick"=>"js:readNotification($data->id)"))'
),
'date_filing',
'next_date',
'panel_lawyer_id',
),
));
?>
here is the script:
<script>
var readNotification = function(id) {
console.log("button clicked with ID: "+id); //getting id here
$.ajax({
type:'POST',
url:'<?php echo Yii::app()->createUrl("notifications/readNotification");?>',
data: {id: id}
});
};
</script>
here is the controller:
public function actionReadNotification(){
echo $_POST['id'];
}
added readNotification function to the accessRules. When clicking on the link new page is loading but ajax request shows error.
Try adding the csrf token inside your data with your ajax request.
<script>
var readNotification = function(id) {
console.log("button clicked with ID: "+id); //getting id here
$.ajax({
type:'POST',
url:'<?php echo Yii::app()->createUrl("notifications/readNotification");?>',
data: {id: id,<?=
Yii::app()->request->csrfTokenName?>:<?=Yii::app()->request->csrfToken?>,}
});
};
</script>
You can also disable the csrftoken by adding the below in the beforeAction()
public function beforeAction($action) {
if($action->id=='readnotification'){
$this->enableCsrfValidation = false;
}
return parent::beforeAction($action);
}
but this is not recommended way of doing the work.
EDIT
i mistakenly added Yii::$app->request instead of Yii::app()->request as the first one is for Yii2 and not for Yii1 please change it to
<?=Yii::app()->request->csrfTokenName?>:<?=Yii::app()->request->csrfToken?>
and make sure you have the request component with the following configurations
'components'=>array(
.
.
.
'request'=>array(
'enableCookieValidation'=>true,
'enableCsrfValidation'=>true,
'csrfTokenName'=>'_my-token',
),
Note : you can change the _my-token to any other name you like
Related
So I have this Form in Blade
{!! Form::select('jobslist[]', $jobs, null, ['id' => 'jobs', 'class' => 'form-control jobs mav-select', 'multiple', 'style' => 'width: 60%; margin-top: 10px;', 'disabled'=>'disabled']) !!`}
I am trying to load $jobs data using Ajax, so I rewrote the form as
{!! Form::select('jobslist[]', [], null, ['id' => 'jobs', 'class' => 'form-control jobs mav-select', 'multiple', 'style' => 'width: 60%; margin-top: 10px;', 'disabled'=>'disabled']) !!}
And added onload script underneath
function loadData(card){
$.ajax({
type: 'POST',
url: '/loadJobs/',
data: {name: card, element: '{{$posting->id}}'},
dataType: 'json',
success: function (response) {
console.log(response);
$("#jobs").html('');
$("#jobs").html(response.options);
})
},
error: function(response){
console.log('Error: ', response["responseText"]);
}
});
}
Through console log I can verify that I am hitting the controller and obtaining data in the format
Object:
options:
27969: "2016-230 :: PL"
27974: "2016-231 :: ML"
27989: "2016-233 :: RF"
how should I pass it to the select box?
You can use append to add the items to select in the success function:
success: function(response){
...
$('#jobs').append('<option value='+response.id+'>' +response.name+ '</option>')
...
}
There you have it, just change 'id' and 'name' as necessary, I hope it helps.
//...
success:function(response){
var len = response.length;
$("#jobs").empty();
for( var i = 0; i<len; i++){
var id = response[i]['id'];
var name = response[i]['name'];
$("#jobs").append("<option value='"+id+"'>"+name+"</option>");
}
}
//...
success: function(data){
console.log('success');
console.log(data);
jobs = data;
$.each(data, function(key, target){
//Use the Option() constructor to create a new HTMLOptionElement.
var option = new Option(target.name, target.id);
//Convert the HTMLOptionElement into a JQuery object that can be used with the append method.
$(option).html(target.name);
//Append the option to our Select element.
$("#jobs").append(option);
//$("#jobs").append("<option> An Option </option>");
});
/
},
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;
});
});
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
I'm getting 422 Unprocessable Entity error even when I'm submitting my form via Ajax.
My javascript file
$.ajaxSetup({
headers: {
'X-XSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('.keywords-plan-form').submit(function(event) {
event.preventDefault();
$.ajax({
url: '/laravel/public/keywordsplans',
type: 'POST',
data: $(this).serialize(),
success: function(data){
alert(data);
// success logic
},
error: function(data){
// Error...
var errors = $.parseJSON(data.responseText);
console.log(errors);
$.each(errors, function(index, value) {
});
}
});
});
as you can see I added X-XSRF-TOKEN****strong text to ajax header.
This is my '' tag
<meta name="csrf-token" content="{{ csrf_token() }}">
my Form Data in chrome debuger
_token:5j6DGhhTytbIRB1GrW9Wml9XrOxmKjgE9RiGa4Gf
date:
keyword[0]:Lorem ipsum
keyword[1]:Is dolor amet
keyword[2]:plumber tampa
Request Headers
X-XSRF-TOKEN:5j6DGhhTytbIRB1GrW9Wml9XrOxmKjgE9RiGa4Gf
.....
am I doing something wrong or forgetting something?
I don't think that csrf token is the issue here. If it were you would get TokenMissmatchException and not Unprocessable Entity.
Do you happen to have a request validator in your Controller like this?
$validator = Validator::make($request->all(), [
'username' => 'required|max:30|min:6|unique:users',
'email' => 'required|email|max:50|unique:users',
'password' => 'required|confirmed|min:6',
]);
If so maybe you can do something like this:
if ($validator->fails()) {
if($request->ajax())
{
return response()->json(array(
'success' => false,
'message' => 'There are incorect values in the form!',
'errors' => $validator->getMessageBag()->toArray()
), 422);
}
$this->throwValidationException(
$request, $validator
);
}
After that you can catch validation errors in your ajax error handler like this:
$('.keywords-plan-form').submit(function(event) {
event.preventDefault();
$.ajax({
url: '/laravel/public/keywordsplans',
type: 'POST',
data: $(this).serialize(),
success: function(data){
alert(data);
// success logic
},
error: function(jqXhr, json, errorThrown){// this are default for ajax errors
var errors = jqXhr.responseJSON;
var errorsHtml = '';
$.each(errors['errors'], function (index, value) {
errorsHtml += '<ul class="list-group"><li class="list-group-item alert alert-danger">' + value + '</li></ul>';
});
//I use SweetAlert2 for this
swal({
title: "Error " + jqXhr.status + ': ' + errorThrown,// this will output "Error 422: Unprocessable Entity"
html: errorsHtml,
width: 'auto',
confirmButtonText: 'Try again',
cancelButtonText: 'Cancel',
confirmButtonClass: 'btn',
cancelButtonClass: 'cancel-class',
showCancelButton: true,
closeOnConfirm: true,
closeOnCancel: true,
type: 'error'
}, function(isConfirm) {
if (isConfirm) {
$('#openModal').click();//this is when the form is in a modal
}
});
}
});
});
And see the messages in the
modal message
Maybe someone will come in handy.
422 Unprocessable Entity
is default error by validator laravel
vendor/laravel/framework/src/Illuminate/Validation/Validator.php
If fails validate params, then throught Exception ValidationException
vendor/laravel/framework/src/Illuminate/Validation/ValidationException.php
where default status = 422
And therethore all your ajax responses with non validate forms will be with status = 422
I have solved this issue :
public function register(\Illuminate\Http\Request $request) {
if ($this->validator($request->all())->fails()) {
$errors = $this->validator($request->all())->errors()->getMessages();
$clientErrors = array();
foreach ($errors as $key => $value) {
$clientErrors[$key] = $value[0];
}
$response = array(
'status' => 'error',
'response_code' => 201,
'errors' => $clientErrors
);
} else {
$this->validator($request->all())->validate();
$user = $this->create($request->all());
$response = array(
'status' => 'success',
'response_code' => 200
);
}
echo json_encode($response);
}
Whoever is still looking for the answer, if you are using Lumen make sure the Request object is a type of Illuminate\Http\Request and not the default one from Lumen.
```function create(Request $request){
I am using codeigniter 2.2.2 with HMVC and a custom session library
I have two views I'll call them V1.php and V2.php for simplicity
and in each view I have a product that can be added to the cart via ajax when you click on the button:
<button class="add-to-cart" id="123" type="button" class="btn btn-fefault cart">
both V1.php and V2.php are sending product details to a controller cart.php to the method add() via ajax
and here is the ajax call in both V1.php and V2.php
$(".add-to-cart").click(function()
{
var target_url = '<?php echo(base_url()."cart/add") ; ?>';
var prod_id = $(this).attr("id");
var qty = 1;
// prepare the data to be sent
var ProductData = {product_id:prod_id,quantity:qty};
$.ajax(
{
url : target_url,
type: "POST",
data : ProductData,
success: function(data)
{
cart = JSON && JSON.parse(data) || $.parseJSON(data);
$("#cart_num").html("( " + cart.num_of_items + " )");
},
error: function(jqXHR, textStatus, errorThrown)
{
$("#cart_notice").show();
$("#cart_notice").html('<pre><code class="prettyprint">AJAX Request Failed<br/> textStatus='+textStatus+', errorThrown='+errorThrown+'</code></pre>');
}
});
// prevent default
return false;
});
and here is the controller cart.php
public function add()
{
$product_id = $this->input->post('product_id');
$quantity = $this->input->post('quantity');
// prepare the array for the cart
$data = array(
'id' => $product_id,
'qty' => $quantity,
'price' => 39.95,
'name' => 'T-Shirt',
'options' => array('Size' => 'L', 'Color' => 'Red')
);
// insert the array in the cart
$cart_flag = $this->cart->insert($data);
//$cart_flag returns false if something went wrong
//$cart_flag returns an id if everything is ok
// prepare the array for the ajax callback function
$cart = array(
'num_of_items' => $this->cart->total_items(),
'total_price' => $this->cart->total()
);
echo json_encode($cart);
}
thanks to debugging tools I could see that :
1.when I add the product from V1.php everything is fine ($cart_flag returns an id)
but
2.when I add the product from V2.php it doesn't add anything ($cart_flag returns FALSE ) although $data is the same in both cases
what I'm I doing wrong ?
the answer was casting, it really gave me a hard time but at last I found it,
the $data looked the same but the type was not
this fixes the problem
$data = array(
'id' => (int)$product_id,
'qty' => (int)$quantity,
'price' => 39.95,
'name' => 'T-Shirt',
'options' => array('Size' => 'L', 'Color' => 'Red')
);
hope this helps someone else with the same issue