Auto Completion Ajax laravel - laravel

Hello I need to do autocompletion to some cities i already have in my db
so my code is like this :
View
<input type="text" name="ville" id="ville" class="small" placeholder="Entrer la ville souhaité">
<script type="text/javascript">
$(function() {
$( "#ville" ).autocomplete({
source:'{!!URL::route('autocomplete')!!}',
minlength:1,
autoFocus:true,
select:function(e,ui)
{
$('#ville').val(ui.item.value);
}
});
});
</script>
Controller
class VilleController extends Controller
{
public function autocomplete(Request $request)
{
$term = $request->term;
$queries = DB::table('ville')
->where('libelle_ville', 'like', '%'.$term.'%')
->take(6)->get();
foreach ($queries as $query)
{
$results[] = ['id' => $query->id, 'value' => $query->libelle_ville]; //you can take custom values as you want
}
return response()->json($results);
}
}
Routes
Route::get('/autocomplete', array('as' => 'autocomplete', 'uses'=>'VilleController#autocomplete'));
It doesn't tells me that I have an error and it doesn't show me any completion either.

Debug json request with laravel is a bit difficult, I recommend you to download this package
https://github.com/ARCANEDEV/LogViewer
or manually open the laravel log in storage/logs/laravel.log and see whats happened

Thanks to Stack and EddyTheDove I found out that the error is that aucomplete is not a function so I have to remove the barkets and $function so it would be something like this in the script tag
<script type="text/javascript">
$( "#ville" ).autocomplete({
source:'{!!URL::route('autocomplete')!!}',
minlength:1,
autoFocus:true,
select:function(e,ui)
{
$('#ville').val(ui.item.value);
}
});
</script>

Related

VueJs & Laravel. I can't send an excel file with Vuejs and FileReader

I would like to load an excel file to send it with axios to Controller and Maatwebsite\Excel for an Import.
The import part in Controller is working when i use Php from blade, i have a problem when sending from my Vuejs Component. I can't Read the Excel File. or Maybe i can't read it in Controller.
This is my code :
<template>
<input type="file" #change="checkFile" />
<button #click="importExcel()">Import File</button>
</template>
<script>
//In method
checkFile(e) {
var files = e.target.files || e.dataTransfer.files;
console.log('#', files); // The file is in console
if (!files.length)
return;
this.createFile(files[0]);
},
createFile(file) {
var reader = new FileReader();
var vm = this;
reader.readAsDataURL(file)
vm.ex.excel=file; // my ex.excel object contain File
},
importExcel: function () {
var formData = new FormData();
formData.append("file", this.ex.excel);
axios.post('/importExcel', formData)
},
</script>
So in Controller, i use this code when i'm using php (working)
public function importExcel(Request $request)
{
if($request->hasFile('import_file')){
Excel::import(new UsersImport, request()->file('import_file'));
}
return back();
}
When i try this code for axios. i have an error :
public function importExcel(Request $request)
{
Excel::import(new UsersImport, $request->excel);
return back();
}
Error: No ReaderType or WriterType could be detected
Console.log(file) in image
UPDATE: In controller i added
$a = $request->excel;
dd($a);
result in : null
<template>
<input type="file" ref="file" #change="checkFile" />
<button #click="importExcel()">Import File</button>
</template>
<script>
//In method
{
...
createFile(file) {
this.ex.excel = this.$refs.file.target.value.files[0]
}
...
}
</script>
<?php
...
public function importExcel(Request $request)
{
Excel::import(new UsersImport, $request->file('file'));
return back();
}
...
looks like the mime-type is missing, try add the mime-type together with your HTTP POST ...

Vue.js with Laravel Permission

I am in the process of integrating Laravel Permission API with Vue.JS frontend. I am using https://github.com/spatie/laravel-permission library for Laravel Permission. I am not understanding how can I check permission in the Vue JS front End (In Laravel blade I am using #Can to check the permission).
I will do a ajax call to check for permissions instead , something like this, but of cours eyou need to modify it to cater your needs.
Routes:
Route::get('/permission/{permissionName}', 'PermissionController#check');
Controller:
function check($permissionName) {
if (! Auth::user()->hasPermissionTo($permissionName)) {
abort(403);
}
return response('', 204);
}
Vue: (if you wanna do this synchronously), this is a simple example (Vue global mixin), you can turn this into Vue directive or component.
Vue.mixin("can", (permissionName) => {
let hasAccess;
axios.get(`/permission/${permissionName}`)
.then(()=> {
hasAccess = true;
}
.catch(()=> {
hasAccess = false;
};
return hasAccess;
});
And then everytime you wanna check permission, you can just do
<el-input v-if="can('write-stuff')"> </el-input>
I'm literally working on this exact same thing. I'm thinking of adding a custom Vue directive that would check against the Laravel.permissions array.
It might even be as simple as
Vue.directive('can', function (el, binding) {
return Laravel.permissions.indexOf(binding) !== -1;
})
I haven't tested this code. Just brainstorming here.
<button v-can="editStuff">You can edit this thing</button>
I can hold permissions this way:
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
'userId' => Auth::user()->id,
'permissions' => Auth::user()->permissions()->pluck('name')->toArray()
]); ?>
Just stumbled upon this problem and I would like to share what I found and implemented.
Add an accessor on the User model the spatie/laravel-permission is using
public function getAllPermissionsAttribute() {
$permissions = [];
foreach (Permission::all() as $permission) {
if (Auth::user()->can($permission->name)) {
$permissions[] = $permission->name;
}
}
return $permissions;
}
On your global page or layout page pass the permission from the accessor to the javascript.
<script type="text/javascript">
#auth
window.Permissions = {!! json_encode(Auth::user()->allPermissions, true) !!};
#else
window.Permissions = [];
#endauth
</script>
Create a global directive on resources/js/app.js
Vue.directive('can', function (el, binding, vnode) {
if(Permissions.indexOf(binding.value) !== -1){
return vnode.elm.hidden = false;
}else{
return vnode.elm.hidden = true;
}
})
Here you are checking if the permission you supplied on the directive is on the permission array from laravel.
If found then it will hide the element else show, this function is like a v-if.
Use it like this on your component - "add_items" is your permission
<button type="button" v-can="'add_items'"></button>
This solution is from this but instead of a mixin, I use a directive.
Got the idea of directive from #Ismoil Shifoev comment above.
You can use this format in Vuejs for Laravel Permission:
<div v-if="can('edit post')">
<!-- Edit post form -->
</div>
<div v-if="is('super-admin')">
<!-- Show admin tools -->
</div>
add function to User Model to get all user permissions&roles like this:
class User extends Authenticatable
{
// ...
public function jsPermissions()
{
return json_encode([
'roles' => $this->getRoleNames(),
'permissions' => $this->getAllPermissions()->pluck('name'),
]);
}
}
pass this data to JavaScript in HTML header:
<script type="text/javascript">
window.Laravel = {
csrfToken: "{{ csrf_token() }}",
jsPermissions: {!! auth()->check()?auth()->user()->jsPermissions():null !!}
}
</script>
in app.js file add global Vuejs can function to check user permissions and is function to check user roles:
Vue.prototype.can = function(value){
return window.Laravel.jsPermissions.permissions.includes(value);
}
Vue.prototype.is = function(value){
return window.Laravel.jsPermissions.roles.includes(value);
}
https://github.com/ahmedsaoud31/laravel-permission-to-vuejs
I would go with Ralph solution. But I find myself better using. This function to fetch the Permissions.
public function getAllPermissionsAttribute() {
return Auth::user()->getAllPermissions()->pluck('name');
}
Just a bit cleaner, and since I tend to use Roles instead of particular permissions for each User, this solution should work as well.

Tag search in laravel vue

I've made a search function to show related projects based on chosen tag and I'm getting results with wrong values
What I've done so far
Create controller function and return results as json
Create route in app.js
Create new component to show results
made axios request to send data to controller and redirect to new component for results
Code
controller
public function areas(Request $request){
$areas = Project::where('area', $request->area)->where('published', '=', 'y')->get();
return response()->json($areas, 200);
}
route in api.php
Route::get('areasearch', 'Api\SearchController#areas');
route in app.js
import AreasPage from './components/areassearch.vue'
{
path: '/areas',
name: 'areas',
props: true,
component: AreasPage,
},
search script + component link
// link
<a v-model.lazy="area" #click="areasearch">{{project.area}}</a>
//script
methods: {
//search in areas
areasearch() {
axios.get('/api/areasearch', {
params: {
area: this.area
}
})
.then(response => {
this.$router.push({
name: 'areas',
params: {
areas: response.data
}
})
})
.catch(error => {});
},
},
results component
<template>
<div>
<navbar></navbar>
<template v-if="areas.length > 0">
<div class="container-fluid counters">
<div class="row text-center">
<div v-for="area in areas" :key="area.id" :to="`/projects/${area.slug}`">
<li>{{area.title}}</li>
</div>
</div>
</div>
</template>
<template v-else>
<p>Sorry there is no area for you, try search new query.</p>
</template>
<footerss></footerss>
</div>
</template>
<script>
import navbar from './navbar.vue';
import footerss from './footer.vue';
export default {
props: ['areas'],
components: {
navbar,
footerss
},
}
</script>
Issue
My link is not behave as a link (is like text when i move mouse over it)
For example if I search for area Jakarta most of results I get is projects where their area column is null.
Any idea?
For the link part, you are using v-model on an anchors, v-model is mainly for inputs, selects, textareas. So
<a v-model.lazy="area" #click="areasearch">{{project.area}}</a>
Should be
<span class="my-link" #click="areasearch(project.area)">{{project.area}}</span>
Use a span, and a class for that span, then on click call your method, i don't know if thats the correct variable for your axios call, btw. it could be project.area.id, or something else...
As for it looking like a link, i assume you are familiar with cursor:pointer css rule.
Your axios part should look something like this:
areasearch(thearea) {
axios.get('/api/areasearch', {
params: {
area: thearea
}
})
.then(response => {
this.$router.push({
name: 'areas',
params: {
areas: response.data
}
})
})
.catch(error => {});
},
As for the controller part:
public function areas(Request $request){
$auxAreas = explode("+", $request->area);
$areas = Project::whereNotNull('area')
->whereIn('area', $auxAreas)
->where('published', '=', 'y')
->get();
return response()->json($areas, 200);
}
first for the wrong result issue try this:
public function areas(Request $request){
$areas = Project::whereNotNull('area')
->where([
['area', $request->area],
['published', '=', 'y']
])->get();
return response()->json($areas, 200);
}

Codeigniter auto suggestion text box

I'm using codeigniter in my project and want to implement a text box which suggests related word s from the data base. In this one I want to get the ID of the selected vehicle. But so far I was only able to retrieve the vehicle names with out IDs.
The code so far,
Model
function searchVehicle($name){
$this->db->like('Name', $name, 'both');
return $this->db->get('vw_vehicle_search')->result();
}
Controller
public function vehicle_search(){
$this->load->model('model_vehicle');
if(isset($_GET['term'])){
$result = $this->model_vehicle->searchVehicle($_GET['term']);
if(count($result)>0){
foreach($result as $object)
$arr_result[] = $object->Name;
echo json_encode($arr_result);
}
}
}
View
<script type="text/javascript">
$(document).ready(function(){
$('#vehicle_name').autocomplete({
source: "<?php echo base_url();?>vehicle/vehicle_search/?"
});
});
</script>
<div class="col-md-4">
<?php
$input_data = array(
'name' => 'vehicle_name',
'id' => 'vehicle_name',
'class' => 'form-control'
);
echo form_input($input_data)?>
</div>
How can I pass the id of the vehicle with this one and get the id when i select a vehicle to insert to the db.
Thank you.
Try it in this way:
controller:
public function vehicle_search(){
$this->load->model('model_vehicle');
if(isset($_GET['term'])){
$result = $this->model_vehicle->searchVehicle($_GET['term']);
if(count($result)>0){
foreach($result as $object)
$arr_result[] = array( 'label' => $object->Name, 'value' => $object->id);
echo json_encode($arr_result);
}
}
}
View:
$(document).ready(function(){
$('#vehicle_name').autocomplete({
source: "<?php echo base_url();?>vehicle/vehicle_search/?",
select: function(event, ui) {
event.preventDefault();
$("#vehicle_name").val(ui.item.label);
//$("#vehicle_name-hidden").val(ui.item.value);
},
focus: function(event, ui) {
event.preventDefault();
$("#vehicle_name").val(ui.item.label);
}
});
});

Username Availablity check in laravel 5 using ajax

On my view page if I am entering username after loader.gif is loading but I am not getting the result for username available or not.. pls give me any ideas...
This is my controller:
public function index()
{
return view('test/username');
}
public function username()
{
$username = Input::get('username');
$users = DB::table('user')
->where('username',$username)
->first();
if ($users !== null)
{
return true;
}
return false;
}
These are my routes:
Route::get('test/username', 'PageController#index');
Route::post('test/username', 'PageController#username');
This is my Blade template:
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#username").change(function () {
$("#message").html("<img src='../images/loader.gif' /> checking...");
var username=$("#username").val();
$.ajax({
type:"post",
url: "{{ URL::to('test/username') }}",
data: {username:username},
success: function (data) {
if (data == 0) {
$("#message").html("<img src='../images/yes.png' /> Username available");
} else {
$("#message").html("<img src='cross.png' /> Username already taken");
}
}
});
});
});
</script>
</head>
<body>
<table>
<tr>
<td>Username</td>
<td>:</td>
<td>
<input type="text" name="username" id="username"/>
</td>
<td id="message"></td>
</tr>
</table>
</body>
</html>
In your routes you are not actually calling the username function declared in your controller but a name one, which doesn't exist. Try modifying your second route to:
Route::post('test/username', 'PageController#username');
There are a few issues with your code. First of all, you should only check for exact usernames instead of using LIKE, or this could match similar usernames. Start by updating your function to (comments in code):
public function username()
{
$username = Input::get('username');
$users = DB::table('user')
->where('username', $username) // exact matches only
->first(); // we only need one result
// instead of count, check that a valid result is returned
if ( $users !== null )
{
return true;
}
// else not required
return false;
}
You need to update your route to call the correct function:
Route::post('test/username', 'PageController#username');
Next, you need to update your JavaScript to correctly send the data to your PHP script. Update the data to:
data: { 'username': username },
If you still get errors, you may need to update the name() function to actually return JSON. You can do this using:
return \Response::json( true );

Resources