Not geeting response of ajax call from Laravel 9 function - ajax

I am trying to get the value of product price from pricing table. For this reason I want user to select the product and in the next field of price the value of product-price will be automatically taken from pricing database table based on product_id passed via ajax from controller.
enter image description here
My route code
public function getPrices(Request $request){$price = \DB::table('pricings')//->select('product_price')->where('product_id',$request->product_id)->get();//dd($request->product_id);if (!empty($price)){return response()->json($price) ;}
}
Above is function in controller to fetch the value of product-price based on 'product_id'.
$(document).ready(function() {$('#productID').on('change', function () {//alert('something changed');var productId = this.value;$('#productPrice').html('');//alert(productId);$.ajax({type: 'get',url: '{{ route("getPrices") }}',data : {product_id:productId},
success: function (response) {
//$('#productPrice').val(res);
alert(response);
},
dataType : "text",
error:function (response){
alert('Error'+response);
}
});
//alert(productId);
});
} );
my ajax code to set the value of price after selecting product.
<th scope="row">1</th><td class="col-sm-3"><div class="form-group row"><div class="col-sm-12"><select class="form-select" name="product_id" id="productID" aria-label="Default select example"><option value="" disabled>Select Product</option>#foreach($product as $products)<option data-tokens="{{ $products->product_name }}" value="{{ $products->id }}" >{{ $products->product_name}} | {{ $products->product_code }} | {{ $products->product_size }} </option>#endforeach</select></div></div></td><td class="col-sm-3"><input type="text" name="price" id="productPrice" class="form-control" placeholder="price" disabled/></td>
My select and text fields on which I am performing this operation.
enter image description here
enter image description here
As I am not getting any value in response when I try to print it on alert.
I just want to have a response from laravel function. If anyone can highlight what is wrong. That would be really helpful.

Related

old() does not work on dependent dropdown in Laravel blade

I have two dropdown list in my Laravel page. I am trying to get old value of the dependent dropdown list (categorylist.blade) and make it selected once I fill and post the data. It returns back to the same page if the validation has not successfully completed. I am able to get all values except this one. I have tried Session::put() as well as Session::flash() but did not work. The category list is retrieved once you chose section as it requests the category list from the controller through ajax. How can I get the old value in the category dropdown list after the page refreshed.
Here is my section selection dropdown:
<select class="form-control sectionchoose" name="section_id" id="section_id">
<option value="">Choose Section</option>
#foreach($sections as $section)
<option value="{{$section['id']}}" #if(old('section_id') == $section['id']) selected #endif>{{$section['name']}} </option>
#endforeach
</select>
My categorylist dropdown:
<label class="col-sm-6">Chose Category</label>
<div class="categorylist">
#include('admin.deal-management.categorylist')
</div>
And this is my categorylist view file:
<select class="form-control " name="category_id" id="category_id">
<option value="">Choose Category</option>
#foreach($categories as $category)
<option value="{{$category['id']}}" #if(old('category_id') == $category['id']) selected #endif>
{{$category['category_name']}}
</option>
#endforeach
</select>
and this is my main controller:
public function addEditDeals(DealAddEditRequest $request, $id=null){
//*** post starts here ***/
if($request->isMethod('post')){
$message = 'Updated successfully';
$data=$request->all();
$deal->fill($request->validated());
$deal->save();
return redirect()->back()->with($message);
}
This is my categorylist controller:
public function findCategories(Request $request){
if($request->json()){
$data = $request->all();
$categories = Category::where(['section_id' => $data['id'], 'status'=>1])->get()->toArray();
return view('admin.deal-management.categorylist',compact('categories'));
}
}
And finally, this is the jQuery part:
$(document).ready(function (){
let sectionid = $('.sectionchoose').val();
$.ajax({
headers: {
'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
},
type: 'POST',
datatype: 'json',
url : '/admin/selectsection',
data: {id:sectionid},
success: function(response){
$('.categorylist').html(response)
}, error:function(){
}
})
})
Finally, I was able to find the solution. Whoever has the same issue can use the approach below:
Step 1: Send the Session value through the with() command:
return redirect()->back()->withErrors($validator)
->withInput()->with('cat_id',$data['category_id']);
}
Step 2: Retreive the data in your main blade and attain hidden input:
<input class="cat_id" id="asd" type="hidden" value="{{Session::get('cat_id')}}"/>
Step 3: Get the retreived session value in Jquery:
$(document).ready(function (){
let sectionid = $('.sectionchoose').val();
let cat_id;
if($('#asd').val()){
cat_id = $('#asd').val();
} else {
cat_id = 0;
}
$.ajax({
headers: {
'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
},
type: 'POST',
datatype: 'json',
url : '/admin/selectsection',
data: {id:sectionid, cat_id:cat_id},
success: function(response){
$('.categorylist').html(response)
}, error:function(){
}
})
})
Step 4: Send the session value to your dependent blade again (as cat_id here)
public function findCategories(Request $request){
if($request->json()){
$data = $request->all();
$cat_id = $data['cat_id'] ?? '';
$categories = Category::where(['section_id' => $data['id'], 'status'=>1])->get()->toArray();
return view('admin.deal-management.categorylist',compact('categories','cat_id'));
}
}
Done! As far as I know, there is not any other way to get old value of dependent dropdown list value so far.

After form submit redirect without refresh using Ajax in laravel 8

I am developing multi Step Form Submit without refresh. collect the data from 1st step 2nd step collect some date, 3rd step collect some date & finally submit data in the database. Can you tell me how to fix this.
My blade template.
<form id="post-form" method="post" action="javascript:void(0)">
#csrf
<div>
<input class="form-input" type="text" id="ptitle" name="ptitle" required="required"
placeholder="What do you want to achieve?">
</div>
<button type="text" id="send_form" class="btn-continue">Continue</button>
</div>
</form>
Ajax Script
$(document).ready(function() {
$("#send_form").click(function(e){
e.preventDefault();
var _token = $("input[name='_token']").val();
var ptitle = $('#ptitle').val();
$.ajax({
url: "{{route('create.setp2') }}",
method:'POST',
data: {_token:_token,ptitle:ptitle},
success: function(data) {
alert('data.success');
}
});
});
Web.php router
Route::post('/setp2', [Abedoncontroller::class, 'funcsetp1'])->name('create.setp2');
Controller method
public function funcsetp1(Request $request) {
$postdata=$request->input('ptitle');
return response()->json('themes.abedon.pages.create-step-2');
}

csrf-token expired before form submit

8
I have a form and I used {!! csrf_field()!!}
I have 2 select element one is for state and one is for the city
when state select change a ajax send and give new cities
if this ajax request doesn't execute we don't have a problem
but if ajax request send then form submit we give 419 page expired error
this is ajax code
$('#state').change(function () {
var state_id = $(this).val();
$.ajax({
type: 'get',
url: '/panel/selectCitiesByStateId/' + state_id,
data: {'nothing': 'nothing'},
timeout: 25000,
error: function () {
alert('sorry error');
},
success: function (res) {
res = JSON.parse(res);
var entires = Object.entries(res);
var htmlOptionElements = '';
for (var i = 0; i < entires.length; i++) {
var city = entires[i];
htmlOptionElements += '<option value="' + city[1] + '">' + city[0] + "</option>";
}
$('#city_id').html(htmlOptionElements);
}
})
});
this is the form top codes
<form action="{{route('admin.job.update',['job'=>$job->slug])}}"
method="post" enctype="multipart/form-data" id="jobForm">
{!! csrf_field() !!}
{!! method_field('patch') !!}
this is select codes
<div class="col-sm-6">
<label for="" class="control-label">state*</label>
<select name="state_id" id="state" class="form-control">
#foreach($states as $state)
<option value="{{$state->id}}"
#if($state->id==#$job->state_id)
selected
#endif
>{{$state->name}}</option>
#endforeach
</select>
</div>
<div class="col-sm-6">
<label for="" class="control-label">city*</label>
<select name="city_id" id="city_id" class="form-control">
#foreach($job->state->cities as $city)
<option value="{{$city->id}}"
#if(#$job->city->id==$city->id)
selected
#endif
>{{$city->name}}</option>
#endforeach
</select>
</div>
well,
one csrf token can be used once. and csrf token generate by a get request.
when you load the form by a get request, token generated and filled the form csrf field.
when the ajax fired on change of #state, you are sending a get request to the system. that means a new csrf token will be generated.
Thats why when you send the request (You already send get request by ajax), you got 419 error.
You can solve this problem by sending post request to ajax for #state, and disable csrf check for the route.
This May solve Your Problem.

Laravel Ajax dropdown example

can someone please share working example of laravel ajax dropdown. there are so many examples about dependable dropdown, but i want simple dropdown of only one column, i have two tables teacher and nation, when teacher profile is open i want dropdown of nationality using ajax.
i have done it without ajax, but i don't know how to do with ajax.
without ajax:
<select name="nation_id" class="custom-select" >
<option selected value=" ">Choose...</option>
#foreach($nations as $nations)
<option value="{{#$nation_id}}" {{#$teacher->nation_id== $nations->id ? 'selected' : ''}} >{{#$nations->nation}}</option>
#endforeach
Controller:
$nations = nation::all();
<select class="form-control" name="nation_id" id="nation_id">
<option value="">Select nation</option>
#foreach($nations as $nation)
<option value="{{ $nation->nation_id }}">{{ $nation->nation_name }} </option>
#endforeach
</select>
<select class="form-control" name="teacher" id="teacher">
</select>
now the ajax code:
<script type="text/javascript">
$('#nation_id).change(function(){
var nid = $(this).val();
if(nid){
$.ajax({
type:"get",
url:"{{url('/getTeacher)}}/"+nid,
success:function(res)
{
if(res)
{
$("#teacher").empty();
$("#state").append('<option>Select Teacher</option>');
$.each(res,function(key,value){
$("#teacher").append('<option value="'+key+'">'+value+'</option>');
});
}
}
});
}
});
</script>
now in controller file;
public function getTeacher($id)
{
$states = DB::table("teachers")
->where("nation_id",$id)
->pluck("teacher_name","teacher_id");
return response()->json($teachers);
}
And last for route file:
Route::get('/getTeacher/{id}','TeachersController#getTeacher');
Hope this will work..
Good Luck...
Create a route for your method which will fetch all the nations-
Route::get('nations-list', 'YourController#method');
Create a method in your controller for the above route-
public function method()
{
$nations = Nation::all()->pluck('nation', 'id');
return response()->json($nations)
}
Add a select box like this in your HTML-
<select id="nation_id" name="nation_id"></select>
If you want to auto select the option based on a variable then you can do this-
<input type="hidden" name="teacher_nation_id" id="teacher_nation_id" value="{{ $teacher->nation_id ?? '' }}">
And then add this script in your HTML to fetch the nation list on page load-
<script>
$(document).ready(function($){
$.get('nations-list', function(data) {
let teacher_nation_id = $('#teacher_nation_id').val();
let nations = $('#nation_id');
nations.empty();
$.each(data, function(key, value) {
nations.append("<option value='"+ key +"'>" + value + "</option>");
});
nations.val(teacher_nation_id); // This will select the default value
});
});
</script>

Laravel Select2 old input after validation

I'm using Select2 in my webapplication. I load my Select2 boxes with Ajax. When validation fails, all the inputs are filled as before except the Select2 box. How can I restore the old value after the form validation fails? My bet was using Request::old('x'), but this inserts the value (in my case an user ID) instead of the selected text. So for example the text John would become 27 in the selectbox. How can I get the text back?
<select id="customer" name="customer" class="searchselect searchselectstyle">
</select>
The js:
token = '{{csrf_token()}}';
$(".searchselect").select2({
ajax: {
dataType: "json",
type: "POST",
data: function (params) {
return {
term: params.term,
'_token': token,
'data' : function(){
var result = [];
var i = 1;
$('.searchselect').each(function(){
result[i] = $(this).val();
i++;
});
return result;
}
};
},
url: function() {
var type = $(this).attr('id');
return '/get' + type;
},
cache: false,
processResults: function (data) {
return {
results: data
};
}
}
});
Edit
The only (dirty) solution I found so far is the following:
<select id="customer" name="customer" class="searchselect searchselectstyle">
#if(Request::old('customer') != NULL)
<option value="{{Request::old('customer')}}">{{$customers->where('id', intval(Request::old('customer')))->first()->name}}</option>
#endif
</select>
$customers is a list of all customers, so this means that for each Select2 box I need to query a big list of items in order to make it work. This will be pretty inefficient if we're talking about thousands of rows per Select2 box.
I guess there must be a better solution. Who can help me?
Normally to programmatically set the value of a select2, you would expect to use the .val() method followed by a .trigger('change') call as per their documentation (and other queries like this on SO). However, select2 themselves have something in their documentation about preselecting options for remotely sourced data.
Essentially their suggestion boils down to (after initalizing your AJAX-driven <select>):
make another AJAX call to a new API endpoint using the pre-selected ID
dynamically create a new option and append to the underlying <select> from a promise function (.then()) after the AJAX call is finished
could also use some of the regular jQuery callback chaining functions for this
trigger a change event
trigger a select2:select event (and pass along the whole data object)
Assuming you're already flashing the old data to the session, Laravel provides handy access to the previously requested input in a variety of ways, notably these three:
static access via the Request class e.g. Request::old('customer') as in the OP
the global old() helper e.g. old('customer'), which returns null if no old input for the given field exists, and can have a default as a second parameter
using the old() method on the Request instance from the controller e.g. $request->old('customer')
The global helper method is more commonly suggested for use inside Blade templates as in some of the other answers here, and is useful when you don't need to manipulate the value and can just plug it straight back in, which you would with things like text inputs.
The last method probably provides you with the answer you're looking for - instead of querying the entire collection from inside of the view, you're able to either manipulate the collection from the controller (similar to the OP, but should be nicer since it's not parsing it in the view) or make another query from the controller based on the old ID and fetch the data you want without having to trawl the collection (less overhead):
$old_customer = Customer::find($request->old('customer'));
Either way, you'd have the specific data available at your fingertips (as a view variable) before the blade template processes anything.
However you choose to inject the data, it would still follow the pattern suggested by select2:
get the pre-selected data
create an option for it
trigger the appropriate events
The only difference being you don't need to fetch the data from another API endpoint (unless you want/need to for other programmatic reasons).
I end up using similar flow like your. But my blade template is using htmlcollection package.
Controller:-
Let's say you are in create() method. When validation failed, it will redirect back to the create page. From this page, you can repopulate the list.
$customer_list = [];
if(old('customer') != NULL){
$customer_list = [old('customer') => $customers->where('id', old('customer'))->first()->name];
}
Blade View:
{{ Form::select('customer', $customer_list, null, ['class' => 'searchselect searchselectstyle', 'id' => 'customer']) }}
I did it with an input hidden for the text and it works well:
This form is showed in a Popup and ajax (using Jquery-UJS)
Form:
<form action="{{ route('store_item', $order) }}" method="POST" data-remote="true">
{{ csrf_field() }}
<div class="form-group{{ $errors->has('item_id') ? ' has-error' : '' }}">
<label class="control-label col-sm-2" for="item_id">Item: </label>
<div class="col-sm-10">
<select name="item_id" class="form-control" id="item_id">
#if(old('item_id') != null)
<option value="{{ old('item_id') }}" selected="selected">
{{ old('item_title') }}
</option>
#endif
</select>
</div>
{!! $errors->first('item_id', '<p class="text-center text-danger"<strong>:message</strong></p>') !!}
</div>
<input type="hidden" id="item_title" name ="item_title" value="{{ old('item_title') }}" />
<div class="form-group{{ $errors->has('quantity') ? ' has-error' : '' }}">
<label class="control-label col-sm-2" for="quantity">Cantidad: </label>
<div class="col-sm-10">
<input name="quantity" type="number" class="form-control" id="quantity" value="{{ old('quantity') }}"/>
</div>
{!! $errors->first('quantity', '<p class="text-center text-danger"><strong>:message</strong></p>') !!}
</div>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary" data-disable-with="Guardando...">Guardar</button>
</form>
JAVASCRIPT:
<script type="text/javascript">
$(document).ready(function(){
$('#item_id').select2({
placeholder: 'Elige un item',
ajax: {
url: '{{ route('select_item_data') }}',
dataType: 'json',
delay: 250,
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
text: item.title,
id: item.id
}
})
};
},
cache: true
}
});
$('#item_id').on('change', function(e){
var title = $(this).select2('data')[0].text;
$('#item_title').val(title);
});
});
</script>
VALIDATION IN STORE METHOD (CONTROLLER):
$validator = Validator::make($request->all(), [
'item_id' => 'required',
'quantity' => 'required'
]);
if ($validator->fails()) {
return redirect()
->route('create_item', $order)
->withInput($request->all())
->withErrors($validator);
}
It's very important to send 'withInput' and 'withErrors' in the redirection, because we are working with a popup and ajax that is created again and doesn't keep the old values.
Maybe you can try (once the ajax call has ended) :
var oldCustomer = $('#customer > option[value={{ Request::old('customer') }}]');
if (oldCustomer.length > 0) {
oldCustomer.attr('selected', 'selected');
}
Same problem; I'm using a similar solution: If the old $id is set, I get the name and I use it as a variable for the view; Note that I also forward the id because I also used this method to pre-fill the form (coming from another place), but in this case, the name only should have been used, and for the id {{ old('author_id') }} can be used in the view:
In the controller:
elseif (($request->old('author_id') !== null) && ($request->old('author_id') != '')) {
$my_author_id = $request->old('author_id');
$my_name = Author::find($my_author_id)->name;
return view('admin/url_author.create', compact('my_name', 'my_author_id'));
}
And in the view (more precisely, in a partial used for creation & edition):
#if (isset($record)) // for use in edit case with laravelcollective)
<select class="form-control js-data-author-ajax" id="author_id" name="author_id">
<option value="{{ $record->author_id }}">{{ $record->author->name }}</option>
</select>
#else
#if (isset($my_name)) // old input after validation + pre-filling cases
<select class="form-control js-data-author-ajax" id="author_id" name="author_id">
<option value="{{ $my_author_id }}">{{ $my_name }}</option>
</select>
#else // for create cases
<select class="form-control js-data-auteur-ajax" id="auteur_id" name="auteur_id">
<option></option>
</select>
#endif
#endif
Your code is bit confusing. I don't understand why you are using a POST request to get data using ajax to fill a select2 box.
Assuming the data returned using ajax call is in the below format.
[
{
"id": "Some id",
"text": "Some text"
},
{
"id": "ID 2",
"text": "Text 2"
},
]
Now what you can do is pass in an extra parameter to your ajax call as below
url: function() {
var type = $(this).attr('id');
#if(old('customer'))
return '/get' + type + '?customer='+ {{ old('customer') }};
#else
return '/get' + type;
#endif
}
Now in your controller while returning data you can throw an extra attribute selected:true for an ID matching that particular ID.
if( Request::has('customer') && Request::input('customer') == $id )
{
[
"id" => $id,
"text" => $text,
"selected" => "true"
]
}
else
{
[
"id" => $id,
"text" => $text,
]
}
If I understood you right I can recommend you to have for each your select2 box hidden input <input type="hidden" name="customer_name" value="{{old('customer_name', '')}}"> where after change event for select2 you can insert selected name (etc. John). So if validation is fails you have:
<select id="customer" name="customer" class="searchselect searchselectstyle">
#if(!is_null(old('customer')))
<option value="{{old('customer')}}">{{old('customer_name')}}
</option>
#endif
</select>
I think your own solution is pretty much correct. You say the list of $customers will get pretty big.
$customers->where('id', intval(Request::old('customer')))->first()
Do you need to have the list stored in a variable $customers? You could just search the id you want
App\Customer::where('id', intval(Request::old('customer')))->first()
Searching by id should not be inefficient. Otherwise you could send the name with the form and store it in the old request. Shown below with some (dirty) javascript.
$("#form").submit( function() {
var sel = document.getElementById("customer");
var text= sel.options[sel.selectedIndex].text;
$('<input />').attr('type', 'hidden')
.attr('name', "selected_customer_name")
.attr('value', text)
.appendTo('#form');
return true;
});
Then like yrv 16s answer:
<option value="{{old('customer')}}">{{old('selected_customer_name')}}
You could do something like this:
First in controller pass tags to view using pluck helper like below:
public function create()
{
$tags= Customer::pluck('name','name');
return view('view',compact('tags'));
}
Then in your form try this:
{!! Form::select('tag_list[]',$tags,old('tag_list'),'multiple','id'=>'tag_list']) !!}
Don't forget to call the select2 function.
$('#tag_list').select2();
And finally in controller:
public function store(ArticleRequest $request)
{
$model = new Model;
$tags=$request->input('tag_list');
$model->tag($tags);
}
Notice tag function is not a helper in Laravel, You implement it! The function takes names and attaches them to the instance of some thing.
Good Luck.

Resources