Select2 Ajax Laravel 5.2 - Paginated results not working? - ajax

I have the following select2 to load remote data with pagination:
$(".js-location-lookup").select2({
ajax: {
url: '/locations',
dataType: "json",
delay: 150,
data: function (params) {
return {
term: params.term,
page: params.page
};
},
processResults: function (data, params) {
params.page = params.page || 1;
return {
results: $.map(data.data, function (item) {
return {
id: item.id,
text: item.name
};
}),
pagination: {
more: (params.page * data.per_page) < data.total
}
};
},
cache: true
},
minimumInputLength: 2,
placeholder: "-- Select --",
allowClear: true
});
Controller action:
public function getLocations(Request $request)
{
$term = $request->input('term');
$data = Location::where('name', 'LIKE', '%'.$term.'%')->paginate(5);
$data->appends(['term' => $term ]);
return response()->json($data);
}
the json:
{
"total":22,
"per_page":5,
"current_page":1,
"last_page":5,
"next_page_url":"/locations?term=en&page=2",
"prev_page_url":null,
"from":1,
"to":5,
"data":[
{"id":1,"name":"England"},
{"id":13,"name":"London (Central)"},
{"id":18,"name":"North East England"},
{"id":23,"name":"North West England"},
{"id":30,"name":"South East England"}
]
}
Only the first page loads and displays the text load more results but it doesn't scroll or do anything to show the next set of results?

If the number of items per page when displayed is less than the height of the dropdown box when it is open then the scroll bars on the select widget do not appear and the above behavior is observed i.e. you are unable to scroll to load the next set of data.
The fix was to increase the pagination to 10 per page so that they are more than the height of the dropdown box.
Not sure if you would class this as a bug.

public function getdataforselect2(Request $request){
if ($request->ajax()) {
$term = trim($request->term);
$posts = DB::table('channels')->select('id','name as text')
->where('name', 'LIKE', '%' . $term. '%')
->orderBy('name', 'asc')->simplePaginate(10);
$morePages=true;
// $pagination_obj= json_encode($posts);
if (empty($posts->nextPageUrl())){
$morePages=false;
}
$results = array(
"results" => $posts->items(),
"pagination" => array(
"more" => $morePages
)
);
return \Response::json($results);
}
}
<script type="text/javascript" src='//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js'></script>
<!--<![endif]-->
<link href="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2#4.1.0-rc.0/dist/js/select2.min.js"></script> <script >
(function() {
$("#channel_id").select2({
placeholder: 'Channel...',
// width: '350px',
allowClear: true,
ajax: {
url: '/dataforselect2',
dataType: 'json',
delay: 250,
data: function(params) {
return {
term: params.term || '',
page: params.page || 1
}
},
cache: true
}
});
})();
</script>
Code here!

Use the following codes with the latest select2 version library.
Controller Codes:
public function getLocations(Request $request)
{
if ($request->ajax()) {
$page = $request->page;
$resultCount = 5;
$offset = ($page - 1) * $resultCount;
$locations = Location::where('name', 'LIKE', '%' . $request->term. '%')
->orderBy('name')
->skip($offset)
->take($resultCount)
->selectRaw('id, name as text')
->get();
$count = Count(Location::where('name', 'LIKE', '%' . $request->term. '%')
->orderBy('name')
->selectRaw('id, name as text')
->get());
$endCount = $offset + $resultCount;
$morePages = $count > $endCount;
$results = array(
"results" => $locations,
"pagination" => array(
"more" => $morePages
)
);
return response()->json($results);
}
return response()->json('oops');
}
View/JS Codes:
$(document).ready(function() {
$('.js-location-lookup').select2({
delay : 200,
ajax: {
url: '/locations',
dataType: 'json',
cache: true,
data: function(params) {
return {
term: params.term || '',
page: params.page || 1
}
},
}
});
});

Related

FullCalendar failed to display events in calendar

I am using FullCalendar in laravel 8 project and I use it to display all the events from the database.
This is the code:
My controller
public function index(Request $request, $id) {
$patient = [];
$listOfPatients = [];
$appointments = [];
//apply permission constraits
$patient = Patient::find($id);
$listOfPatients = Patient::all();
$appointments = appointments::all();
$this->authorize('view', $patient);
// $appointments = $patient->remarks()->get()->sortBy([['id', 'desc']]);
if($request->ajax()) {
$data = appointments::whereDate('start', '>=', $request->start)
->whereDate('end', '<=', $request->end)
->get(['id', 'title', 'description', 'start', 'end']);
return response()->json($data);
}
return view('patient.appointments', [ "appointments" => $appointments, "patient" => $patient, "listOfPatients" => $listOfPatients]);
}
My js
$(document).ready(function () {
var SITEURL = "{{ url('/') }}";
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var calendar = $('#full_calendar_events').fullCalendar({
editable: false,
editable: false,
eventSources: [
{
url: '/{id}/appointments',
color: '#65a9d7', // an option!
textColor: '#3c3d3d' // an option!
}
],
});
});
I also got this error:
jquery.min.js:4 GET http://127.0.0.1:8000/%7Bid%7D/appointments?start=2022-02-27&end=2022-04-10&_=1648373948124 404 (Not Found)

laravel filter ajax and pagination

I want to filter products in my category with price desc or asc or newest(id desc). But my ajax filter only action in first page
This is my view and script:
<script type="text/javascript">
function sort(value) {
$.ajax({
type: 'get',
url: '{!!URL::to('cate/update') !!}',
data: {'sort': value, 'id': {{ $id }} },
}).done(function (data) {
$('body').html(data)
}).fail(function (data) {
console.log(data);
});
}
</script>
This is my controller:
if ($request->sort == 1) {
$data['items'] = Product::where('prod_cate', $request->id)->orderby('promotion_price', 'asc')->paginate(3);
} else if ($request->sort == 2) {
$data['items'] = Product::where('prod_cate', $request->id)->orderby('promotion_price', 'desc')->paginate(3);
}else{
$data['items'] = Product::where('prod_cate', $request->id)->orderby('prod_id', 'desc')->paginate(3);
}
return view('frontend.product_type', $data);

How to set select2 (Ajax) default value

How to define select2 default AJAX value?
I've tried many but still cannot get it working.
Below is my code:
$("#qrcode_group_rowid").select2({
ajax: {
url: "app/qrcode/qrcode_group_select_service.php",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, params) {
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 50) < data.total_count
}
};
},
cache: true
},
placeholder: 'Please select',
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 0,
templateResult: formatRepo,
templateSelection: formatRepoSelection
});
function formatRepo (json) {
if (json.loading) {
return json.text;
}
var markup = json.group_name;
return markup;
}
function formatRepoSelection (json) {
return json.group_name;
}
and my JSON data:
{
"total_count": 897,
"items": [{"id": 901,"group_name": "TEST25-117"},{"id": 1,"group_name": "TEM117"}]
}
What am I doing wrong and how can I fix it?
You should send the following information in the PHP method (there may be a limitation of working with the IP address in eloquent)
/** #var Collection $btsNodes */
$btsNodes = BtsNode::where('node_code' , 'like' , '%'.$request->get('q').'%')
->get(['node_code']);
// ->toArray();
$items = $btsNodes->map(function ($item){
return [
'id' => $item['node_code'],
'node_code' => $item['node_code']
];
});
return ['items' => $items];

Download maatwebsite excel using ajax in laravel

I'm trying to download an excel file using ajax method in laravel.
Controller function:
$myFile = Excel::create($name, function ($excel) use ($export) {
$excel->sheet('Data', function ($sheet) use ($export) {
$sheet->fromArray($export);
$sheet->cells('A1:N1', function ($cells) {
$cells->setBackground('#dbdbdb');
$cells->setFontColor('#000000');
$cells->setFontWeight('bold');
$cells->setFont(array(
'family' => 'Calibri',
'size' => '9',
));
});
$sheet->setStyle(array(
'font' => array(
'name' => 'Calibri',
'size' => 9,
),
));
});
});
$myFile = $myFile->string('xlsx');
$response = array(
'name' => $name,
'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64," . base64_encode($myFile),
);
return response()->json($response);
Ajax function:
$(document).on('click', '.ExportJobs', function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var ids = [];
$(".InvoiceCheckBox:checked").each(function(e) {
ids.push(this.value);
});
data = {
"ids": ids,
};
$.ajax({
method: "POST",
url: "/exportNew",
data: data,
success: function(response) {
var a = document.createElement("a");
a.href = response.file;
a.download = response.name;
document.body.appendChild(a);
a.click();
a.remove();
}
});
});
But using above controller method is not returning excel formatted file if I change string value from xlsx to csv then csv formatted file is getting downloaded.
How do we make the excel formatted file downloaded? Any suggestions, Please!
I know this is quite late, but posting for others who struggle with same issue like me
I also needed to download excel from using Maatwebsite excel library by using ajax post call.
added a button to fire the ajax call to download excel file
<button onclick="downloadExcel()" id="btn-download-payroll" class="btn btn-dark-success btn-md" style="transform: translateY(50%); top: 50%; font-size: 13px;"><i aria-hidden="true" class="fa fa-cog mr-10"></i>
Download
</button>
Used following js code to post ajax request
function downloadExcel() {
var salaryMonth = $("#dp-salary-month").datepicker("getDate");
var department = $("#cbox-department");
var month = new Date(salaryMonth).getMonth() + 1;
var year = new Date(salaryMonth).getFullYear();
$.ajax({
xhrFields: {
responseType: 'blob',
},
type: 'POST',
url: '/downloadPayroll',
data: {
salaryMonth: month,
salaryYear: year,
is_employee_salary: 1,
department: department.val()
},
success: function(result, status, xhr) {
var disposition = xhr.getResponseHeader('content-disposition');
var matches = /"([^"]*)"/.exec(disposition);
var filename = (matches != null && matches[1] ? matches[1] : 'salary.xlsx');
// The actual download
var blob = new Blob([result], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
});
}
in routes/web.php file set the reoute for my controller
Route::post('/downloadPayroll', 'Payroll\\Process\\PayrollController#downloadPayroll');
Here I used maatwebsite/excel library to generate excel file with FromQuery approach but due to library update Excel::create has been replaced by Excel::download in "maatwebsite/excel": "^3.1" I used download method in my case here is my HelperClass to generate records according to my requirement
PayrollHelper.php
namespace App\Http\Helpers;
use App\PayrollEmployee;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\Exportable;
class PayrollHelper implements FromQuery
{
use Exportable;
public function forDepartment(int $department)
{
$this->department = $department;
return $this;
}
public function forMonth(string $month)
{
$this->month = $month;
return $this;
}
public function query()
{
// get the salary information for the given month and given department
return PayrollEmployee::query()->where(['salary_month' => $this->month,'department_id'=>$this->department]);
}
}
finally in my controller
class PayrollController extends Controller
{
public function downloadPayroll(Request $request)
{
$file_name = '';
try {
$requestData = $request->all();
$salary_month = $requestData['salaryMonth'];
$salary_year = $requestData['salaryYear'];
$department = $requestData['department'];
$is_employee_salary = boolval($requestData['is_employee_salary']);
$month = Carbon::createFromDate($salary_year, $salary_month);
$month_start = Carbon::parse($month)->startOfMonth();
$formated_month = Carbon::parse($month)->format('F Y');
$file_name = 'Employee_salary_' . $formated_month . '.xlsx';
// to download directly need to return file
return Excel::download((new PayrollHelper)->forMonth($month_start)->forDepartment($department), $file_name, null, [\Maatwebsite\Excel\Excel::XLSX]);
} catch (exception $e) {
}
}
}
After creating excel file return file to get as ajax response as blob
That's all
Just see the xhrFields to set responseType as blob and then see the ajax success part. Hope you everyone find the solution:
<script>
$(document).ready(function(){
$("#ExportData").click(function()
{
dataCaptureExport();
});
});
function dataCaptureExport(){
var FromDate = $('#dateFrom').val();
var ToDate = $('#dateTo').val();
var dataString = { FromDate: FromDate, ToDate:ToDate, _token: '{{csrf_token()}}'};
$.ajax
({
type: "POST",
url: '{{ route('invoice_details_export') }}',
data: dataString,
cache: false,
xhrFields:{
responseType: 'blob'
},
success: function(data)
{
var link = document.createElement('a');
link.href = window.URL.createObjectURL(data);
link.download = `Invoice_details_report.xlsx`;
link.click();
},
fail: function(data) {
alert('Not downloaded');
//console.log('fail', data);
}
});
}
It's late but help for others
You can do this way
In Ajax
$(document).on('click', '#downloadExcel', function () {
$("#downloadExcel").hide();
$("#ExcelDownloadLoader").show();
$.ajax({
url: '{{ route("admin.export_pending_submitted_tasks") }}',
method: "GET",
cache: false,
data: {
search_partner,
search_state,
search_city,
_token,
},
success: function (response) {
var a = document.createElement("a");
a.href = response.file;
a.download = response.name;
document.body.appendChild(a);
a.click();
a.remove();
$("#downloadExcel").show();
$("#ExcelDownloadLoader").hide();
},
error: function (ajaxContext) {
$("#downloadExcel").show();
$("#ExcelDownloadLoader").hide();
alert('Export error: '+ajaxContext.responseText);
}
});
});
In Controller
// Get pending submitted tasks export excel
public function export_pending_submitted_tasks(Request $request){
$input = $request->input();
$pending_submitted_tasks = SubmittedTask::select('id', 'partner', 'se_id', 'description', 'created_at', 'status', 'updated_at');
(isset($input['search_partner'])) ? $pending_submitted_tasks->where('partner_id', $input['search_partner']) : '';
(isset($input['search_partner'])) ? $pending_submitted_tasks->where('state', 'like', '%'.$input['search_state'].'%') : '';
(isset($input['search_partner'])) ? $pending_submitted_tasks->where('city', 'like', '%'.$input['search_city'].'%') : '';
$pendingTaskList = $pending_submitted_tasks->where('status', 'pending')->get();
if($pendingTaskList->count() > 0):
$myFile = Excel::raw(new ExportPendingTaskHelper($pendingTaskList), 'Xlsx');
$response = array(
'name' => "Pending-Task-List.xlsx",
'file' => "data:application/vnd.ms-excel;base64,".base64_encode($myFile)
);
return response()->json($response);
else:
return back()->with('message', 'No Pending tasks available to download!!');
endif;
}
If you are using jquery:
// In controller:
return Excel::download(new SomeExport, 'Some_Report.xlsx', null, [\Maatwebsite\Excel\Excel::XLSX]);
// Ajax:
$.ajax({
type: 'GET',
url: '{{ route("some.route") }}',
data: {
"_token": "{{ csrf_token() }}"
},
xhrFields:{
responseType: 'blob'
},
beforeSend: function() {
//
},
success: function(data) {
var url = window.URL || window.webkitURL;
var objectUrl = url.createObjectURL(data);
window.open(objectUrl);
},
error: function(data) {
//
}
});

Istotope ajax content load

I'm stuck implementing load next set of posts in WordPress with isotope masonry layout.
It's just not triggered for appended elements and I can't figure out why.
If someone could point me in right direction I would appreciate.
jQuery AJAX function
function load_content( args ) {
$container = $('#container-async');
$status = $('.status');
$.ajax({
url: ajax_url,
data: {
action: 'do_load_posts',
nonce: nonce,
args: args
},
type: 'post',
dataType: 'json',
success: function( data, textStatus, XMLHttpRequest ) {
$items = data.posts;
if ( args.action === 'filter') {
/**
* Replace items
*/
$container.imagesLoaded( function() {
$container.isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer'
}
});
$container.html( $items ).isotope( 'appended', $items, function() {
console.log('inserted');
});
});
}
else {
/**
* Append items
*/
$container.imagesLoaded( function() {
$container.isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer'
}
});
$container.append( $items ).isotope( 'appended', $items, function() {
console.log('appended');
});
});
}
},
error: function( MLHttpRequest, textStatus, errorThrown ) {
$status.toggleClass('active');
}
});
}
WordPress AJAX:
function ajax_do_load_posts() {
// Verify nonce
if( !isset( $_POST['nonce'] ) || !wp_verify_nonce( $_POST['nonce'], 'nonce' ) )
die('Permission denied');
$response = [
'status' => 500,
'posts' => 0,
];
$filter = $_POST['args'];
$type = get_post_type_object( $filter['type'] );
$args = [
'post_type' => sanitize_text_field($filter['type']),
'paged' => intval($filter['page']),
'posts_per_page' => $filter['qty'],
];
$qry = new WP_Query($args);
if ($qry->have_posts()) :
ob_start();
while($qry->have_posts()) : $qry->the_post(); ?>
<div class="grid-item col-xs-12 col-sm-6 col-md-4 col-lg-3">
<?php get_template_part('templates/loop', 'card' ); ?>
</div>
<?php endwhile;
$response = [
'status' => 200,
'posts' => ob_get_clean(),
];
endif;
wp_reset_query();
wp_reset_postdata();
die(json_encode($response));
}
add_action('wp_ajax_do_load_posts', 'ajax_do_load_posts');
add_action('wp_ajax_nopriv_do_load_posts', 'ajax_do_load_posts');
Items are inserted or appended into container but masonry is triggered only on items that are already there on page load.
I have googled around and tried various solutions but none of them work, neither with isotope or masonry jquery plugin.
I was able to fix my issue, and kind of looks like the problem is because I was using jQuery default append/insert methods.
I have switched to isotope methods and now things look fine.
So basically instead of
$container.html( $items ).isotope( 'appended', $items, function() {
console.log('inserted');
});
I am now using:
$grid.isotope('insert', jQuery($items));
It looks logical actually that isotope cannot know items are appended if I don't use isotopes append/insert method. And notice that I also wrapped $items inside jQuery.
Anyhow my working JS for same PHP function is:
function load_content( args ) {
$container = $('#container-async');
$status = $('.status');
$.ajax({
url: ajax_url,
data: {
action: 'do_load_posts',
nonce: nonce,
args: args
},
type: 'post',
dataType: 'json',
success: function( data, textStatus, XMLHttpRequest ) {
$items = data.posts;
var $grid = $('.masonry').imagesLoaded( function() {
$grid.isotope({
itemSelector: '.grid-item',
percentPosition: true,
masonry: {
columnWidth: '.grid-sizer'
}
});
if ( args.action === 'filter') {
$grid.isotope('remove', $('.grid-item'));
}
$grid.isotope('insert', jQuery($items));
});
$grid.on( 'layoutComplete', function( event, laidOutItems ) {
$container.removeClass(data.action);
});
},
error: function( MLHttpRequest, textStatus, errorThrown ) {
$status.toggleClass('active');
}
});
}

Resources