Autocomplete Search not Working in Laravel - php

I have a search field with the same name and id inside my categories page and inside my products page.The autocomplete suggestions seems to work fine , however once I click on requested product inside the search field, it's stays on the same page and not redirecting me to the view.I want my view to show only products. This is my code so far:
After update
My routes:
<?php
Route::get('products/{id}', 'AutoCompleteController#show');
Route::get('autocomplete', array('as' => 'autocomplete', 'uses' => 'AutoCompleteController#show'));
Route::get('searchajax', array('as' => 'searchajax', 'uses' => 'AutoCompleteController#autoComplete'));
My AutoCompleteController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\MainController;
use App\Product;
class AutoCompleteController extends MainController
{
public function show(Product $product)
{
return view('content.products', ['product' => $product]);
}
public function autoComplete(Request $request)
{
$query = $request->get('term', '');
$products = Product::where('title', 'LIKE', '%' . $query . '%')->get();
$data = [];
foreach ($products as $product) {
$data[] = array('label' => $product->title, 'value' => $product->id);
}
if (count($data)) {
return $data;
} else {
return ['value' => 'No Result Found', 'id' => ''];
}
}
}
My view in products.blade.php and categories.blade.php for my autocomplete search is the same:
#extends('master')
#section('content')
<link href="http://demo.expertphp.in/css/jquery.ui.autocomplete.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div class="row">
<form class="navbar-form text-center " form method="GET" action=" ">
<input id="search_text" placeholder=" Search products" name="search_text" type="text" value=""
style="width: 400px; height: 35px; border-radius: 5px ; padding-left: 12px;"><br><br>
<input class="btn btn-default " type="submit" value=" Search">
</form>
</div>
<script>
$(document).ready(function () {
src = "{{ route('searchajax') }}";
$("#search_text").autocomplete({
source: function (request, response) {
$.ajax({
url: src,
dataType: "json",
data: {
term: request.term
},
success: function (data) {
response(data);
}
});
},
minLength: 3,
select: function (event, ui) {
window.location = '{{ url('shop/{category_url}')}}' + ui.item.id
} // not sure if this is the correct way , please advise
});
});
</script>
#endsection

If you seems the issue with JS conflict, try below code:
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
Added missing ui css too. Let me know the result.

There are a few problems:
An autocomplete response should include label and value pairs, you are returning value and id. See the jQuery UI source docs.
Your Javascript is missing the select event handler, which specifies what happens when one of the suggestions is selected. So right now clicking one will just fill the clicked value in the input field. See the jQueryUI autocomplete select docs.
Maybe you want to be able to view product ID 1 when you browse to /products/1. First you need to set up a route for that:
Route::get('products/{id}', 'AutoCompleteController#index');
Then in your controller, first fix the autocomplete response to return the right format:
foreach ($products as $product) {
$data[]=array('label'=>$product->title,'value'=>$product->id);
}
Next, still in the controller, update the method for showing your product (BTW this should probably be called show, index would usually be a list of products:
use App\Product;
class AutoCompleteController extends MainController {
// This assumes you have a Product model
public function index(Product $product) {
return view('content.products', ['product' => $product]);
}
And your Javascript:
$("#search_text").autocomplete({
source: function (request, response) {
$.ajax({
url: src,
dataType: "json",
data: {
term: request.term
},
success: function (data) {
response(data);
}
});
},
minLength: 3,
select: function( event, ui ) {
// Your autoComplete response returns the ID in the 'value' field
window.location = 'http://yoursite.com/products/' + ui.item.value
}
});

Related

Confirm delete using sweetalert in Laravel Form Collective

I'm a beginner in using laravel, please help.
I'm using sweet alert to ask for confirmation before deleting. The error says that it is missing a required parameter for destroy, though I am certainly sure that I am passing an id to the function destroy.
Here's my code
Announcement.blade.php
#extends('masterlayout')
#section('title')Announcement #endsection
#section('myHeader')
<div class="container myJumbotron">
<h1>ANNOUNCEMENTS</h1>
#if(count($announcements) > 0)
#foreach($announcements as $announce)
<div class="jumbotron" style="margin-top: 20px; padding: 20px">
<input type = "hidden" class = "deletebtn_id" value = "{{ $announce->id}}">
<p>{{$announce->announcement}}</p>
<small>Written on {{$announce->created_at}}</small>
<hr>
Edit
{!!Form::open(['action' => ['AnnouncementsController#destroy',$announce->id], 'method' => 'POST', 'class' => 'float-right'])!!}
{{Form::hidden('_method', 'DELETE')}}
{{Form::submit('Delete', ['class' => 'btn bg-OwnDanger myDeletebtn'])}}
{!!Form::close()!!}
</div>
#endforeach
{{$announcements->links()}}
#endif
</div>
<div class="container">
<div class="float-right">
New Announcement
</div>
</div>
#include('AnnouncementsFolder.delete_scripts')
#endsection
delete_script.blade.php
<script>
$(document).ready(function() {
$('.myDeletebtn').click(function(e) {
e.preventDefault();
delete_id = $(this).closest("div").find('.deletebtn_id').val();
data_id = delete_id
//alert(data_id);
swal({
title: "Are you sure?",
text: "Once deleted, you will not be able to recover this imaginary file!",
icon: "warning",
buttons: true,
dangerMode: true,
})
.then((willDelete) => {
if (willDelete) {
$.ajax({
type: "DELETE",
url: "{{ route('announcements.destroy') }}" + '/' + delete_id,
success: function() {
swal("Poof! Your imaginary file has been deleted!", {
icon: "success",
});
}
});
} else {
swal("Your imaginary file is safe!");
}
});
});
});
</script>
destroy function in AnnouncementsController.php
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
$announcements = Announcement::find($id);
$announcements->delete();
return redirect('/announcements');
}
Route
Route::resource('announcements', 'AnnouncementsController');
The error is this:
Missing required parameters for [Route: announcements.destroy] [URI: announcements/{announcement}]. (View: C:\xampp\htdocs\Websys_2_Project\resources\views\AnnouncementsFolder\delete_scripts.blade.php)
Change
url: "{{ route('announcements.destroy') }}" + '/' + delete_id,`
to
url: "/announcements/" + delete_id,`

Laravel pagination without refreshing page

I found this Ajax for pagination without refreshing the page.
Pagination works, but page is refreshing every time, it's annoying because table is on bottom of the page.
Can you check, maybe I made some mistake. Or give me some ideas to fix this.
Controller:
public function index(Request $request)
{
$satwork = DB::table('companies')
->leftJoin('devices', 'companies.id', '=', 'devices.companyId')
->leftJoin('vehicles', 'devices.id', '=', 'vehicles.deviceId')
->leftJoin('drivers', 'vehicles.id', '=', 'drivers.vehicleId')
->select('companies.company_name', 'devices.device_type', 'vehicles.license_plate', 'drivers.driver_name')
->paginate(5);
return view('/welcome', compact('satwork'));
}
public function fetch_data(Request $request)
{
if ($request->ajax())
{
$satwork = DB::table('companies')
->leftJoin('devices', 'companies.id', '=', 'devices.companyId')
->leftJoin('vehicles', 'devices.id', '=', 'vehicles.deviceId')
->leftJoin('drivers', 'vehicles.id', '=', 'drivers.vehicleId')
->select('companies.company_name', 'devices.device_type', 'vehicles.license_plate', 'drivers.driver_name')
->paginate(5);
return view('pagination', compact('satwork'))->render();
}
}
welcome.blade
<div class="container">
<div id="table_data">
#include('pagination')
</div>
</div>
</div>
<!-- pagination -->
<script>
$(document).ready(function() {
$(document).on('click', '.pagination a', function(event) {
event.preventDefault();
var page = $(this).attr('href').split('page=')[1];
fetch_data(page);
});
function fetch_data(page) {
$.ajax({
url: "//pagination?page=" + page,
success: function(satwork) {
$('#table_data').html(satwork);
}
});
}
});
}
</script>
pagination blade
<tbody>
#foreach ($satwork as $row)
<tr>
<td>{{ $row -> company_name}}</td>
<td>{{ $row -> device_type}}</td>
<td>{{ $row -> license_plate}}</td>
<td>{{ $row -> driver_name}}</td>
</tr>
#endforeach
</tbody>
{!! $satwork->links() !!}
routes
Route::get('/', 'WelcomeController#index');
Route::get('/welcome/pagination', 'WelcomeController#fetch_data');
Your ajax request URL to fetch the pagination is not correct.
url: "//pagination?page=" + page
That should be url: "/welcome/pagination?page=" + page
function fetch_data(page) {
var l = window.location;
// the request path should be
// domain.com/welcome/pagination
$.ajax({
url: l.origin + l.pathname + "?page=" + page,
success: function(satwork) {
$('#table_data').html(satwork);
}
});
}
It can be done with dataTables
Script:
<script>
$(document).ready(function() {
$('#companies').DataTable({
"lengthMenu": [[2, 3, 5, 10, 20, -1], [2, 3, 5, 10, 20, "All"]]
});
});
</script>
Style:
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/jquery.dataTables.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.js"></script>
And it's working.

Implementing Searchable, a search trait for Laravel

I was trying to implement a searchable function using Searchable, a search trait for Laravel by nicolaslopezj, i have used the following code. But it doesn't seem to work. If there are only two records in the database it show the records but if more then two records it doesn't search.
Model: Contact.php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Nicolaslopezj\Searchable\SearchableTrait;
class Contact extends Model
{
use SearchableTrait;
protected $searchable = [
'columns' => [
'contacts.first_name' => 10,
'contacts.last_name' => 10,
]];
}
Controller: SearchController
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Nicolaslopezj\Searchable\SearchableTrait;
use View;
use App\Contact;
use App\Tag;
use App\Project;
use App\User;
//use Illuminate\Support\Facades\Input;
class SearchController extends Controller
{
public function findContact(Request $request)
{
return Contact::search($request->get('cname'))->get();
}
public function contactPrefetch()
{
$all_contacts= Contact::All();
return \Response::json($all_contacts);
}
}
View: show.blade.php
<script src="{{asset('global/js/plugins/datatables/jquery.dataTables.min.js')}}"></script>
<script src="{{asset('global/js/pages/base_tables_datatables.js')}}"></script>
<div class="input-group input-medium " style="float: right; padding-top: 3px; ">
<input type="search" name="cname" class="form-control search-input" placeholder="search contact" autocomplete="off" >
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<!-- Bootstrap JS -->
<!-- Typeahead.js Bundle -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/typeahead.js/0.11.1/typeahead.bundle.min.js"></script>
<script>
jQuery(document).ready(function($) {
// Set the Options for "Bloodhound" suggestion engine
var engine = new Bloodhound({
prefetch: '/find_contact_all',
remote: {
url: '/find_contact?q=%QUERY%',
wildcard: '%QUERY%'
},
datumTokenizer: Bloodhound.tokenizers.whitespace('cname'),
// queryTokenizer: Bloodhound.tokenizers.whitespace
});
$(".search-input").typeahead({
hint: true,
highlight: true,
minLength: 1
}, {
source: engine.ttAdapter(),
name: 'contact',
display: function(data) {
return data.first_name + ' '+ data.last_name ;
},
templates: {
empty: [
'<a class="list-group-item"> Agent not found.</a>'
],
header: [
'<div class="list-group search-results-dropdown">'
],
suggestion: function (data) {
return '' + data.first_name + ' ' + data.first_name + ''
}
}
});
});
</script>
Routes:
Route::get('find_contact', 'SearchController#findContact');
Route::get('find_contact_all', 'SearchController#contactPrefetch');
Simply add the package to your "composer.json" file and "composer update"[update your composer]
"nicolaslopezj/searchable": "1.*"

Laravel token missmatch exception

I am trying to upload image by ajax. I am using Croppic Master but when I upload the image, it gives me token miss match exception. How to pass token in the below code?
<div class="col-lg-4 ">
<div id="cropContaineroutput">
</div>
<input type="text" id="cropOutput" style="width:100%; padding:5px 4%; margin:20px auto; display:block; border: 1px solid #CCC;" />
JS
var croppicContaineroutputOptions = {
uploadUrl: '<?php echo url()?>/users/cover',
cropUrl: 'img_crop_to_file.php',
outputUrlId: 'cropOutput',
modal: false,
loaderHtml: '<div class="loader bubblingG"><span id="bubblingG_1"></span><span id="bubblingG_2"></span><span id="bubblingG_3"></span></div> ',
onBeforeImgUpload: function () {
console.log('onBeforeImgUpload')
},
onAfterImgUpload: function () {
console.log('onAfterImgUpload')
},
onImgDrag: function () {
console.log('onImgDrag')
},
onImgZoom: function () {
console.log('onImgZoom')
},
onBeforeImgCrop: function () {
console.log('onBeforeImgCrop')
},
onAfterImgCrop: function () {
console.log('onAfterImgCrop')
},
onReset: function () {
console.log('onReset')
},
onError: function (errormessage) {
console.log('onError:' + errormessage)
}
}
var cropContaineroutput = new Croppic('cropContaineroutput', croppicContaineroutputOptions);
I had the same problem with ajax request and the trick bellow solved the problem.
Add the token in your template:
<meta name="csrf-token" content="{{ csrf_token() }}">
Then in your javascript:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
Another way to include the token into your AJAX calls:
/** inside your blade **
<script>
var token = '{{csrf_token()}}'
$.ajax('url/to/api', {
....
data: {
....
'_token' : token
}
}
</script>
Essentially, as long as your request has the CSRF token within a field called _tokenit should work.

Ajax image load after dropzone success event

So I am using dropzone.js and I want to reload a particular image after the success event of dropzone.
my controller
public function edit($id)
{
$offer = Offer::find($id);
if(!is_object($offer->getMedia('featimgs')->first())){
$offerfeatimg = '/assets/images/offerfeatimg.jpg';
} else {
$offerfeatimg = $offer->getMedia('featimgs')->first()->getUrl('medium');
}
return view('admin.offers.edit')->with(compact('offer', 'offerfeatimg'));
}
so this is where I pass the image to the view:
<div class="panel-body">
<img src="{{ $offerfeatimg }}" class="img-responsive">
#if($offerfeatimg != '/assets/images/offerfeatimg.jpg')
<div class="removebutton">
Izbrisi sliku
</div>
#endif
<form action="/admin/offer/featimg/{{ $offer->id }}" class="dropzone" id="my-awesome-dropzone">
{!! csrf_field() !!}
<div class="dz-message">Prebacite glavnu sliku za ovu ponudu</div>
</form>
</div>
the view:
so I would want to reload this part via ajax after success dropzone event:
<img src="{{ $offerfeatimg }}" class="img-responsive">
#if($offerfeatimg != '/assets/images/offerfeatimg.jpg')
<div class="removebutton">
Izbrisi sliku
</div>
#endif
Any ideas ?
This is assuming a bit about your javascript setup, including jquery. If the dropzone object is available on the form node, you should be able to do something like this in javascript:
var dz = $('form.dropzone').get(0).dropzone;
dz.on("success", function (file, response) {
var imageSrc = ... // add logic here to determine src from server response
$(".img-responsive").attr('src', imageSrc);
if(imageSrc != '/assets/images/offerfeatimg.jpg') {
$(".removebutton").hide();
}
else {
// you may need to edit your html so that this button exists in order to show it
$(".removebutton").show();
}
});
Or you can set up event handlers like this:
Dropzone.options.myAwesomeDropzone = {
... other options ...,
success: function () {
...
}
};
Take a look at handling dropzone events: http://www.dropzonejs.com/#events
Dropzone.options.myAwesomeDropzone = {
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 2, // MB
parallelUploads: 1,
success: function (file, response) {
var imageSrc = response;
$(".img-responsive").attr('src', imageSrc);
if(imageSrc == '/assets/images/offerfeatimg.jpg') {
$(".removebutton").hide();
} else {
$(".removebutton").show();
}
this.removeAllFiles();
}
};

Categories