I am using Laravel and Vue Js for the data listing and paginate data using vue component, without using component my code works fine but when i use component pagination bar is working but not sync with listing,
Here is my Html
<!DOCTYPE html>
<html>
<head>
<title>Users List</title>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css">
</head>
<body>
<div class="container" id="users">
<!-- Item Listing -->
<table class="table table-bordered">
<tr>
<th>Name</th>
<th>Email</th>
<th>Created At</th>
</tr>
<tr v-for="user in users">
<td>#{{ user.name }}</td>
<td>#{{ user.email }}</td>
<td>#{{ user.created_at }}</td>
</tr>
</table>
<vue-pagination></vue-pagination>
</div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/vue.resource/0.9.3/vue-resource.min.js"></script>
<script type="text/javascript" src="/js/users.js"></script>
</body>
</html>
And Here is my Vue Js Code
var VueComponent = Vue.extend({
template:
'<nav>' +
'<ul class="pagination">' +
'<li v-if="pagination.current_page > 1">' +
'<a href="#" aria-label="Previous" #click.prevent="changePage(pagination.current_page - 1)">' +
'<span aria-hidden="true">«</span>' +
'</a>' +
'</li>' +
'<li v-for="page in pagesNumber" :class="{\'active\': page == pagination.current_page}">' +
'{{ page }}' +
'</li>' +
'<li v-if="pagination.current_page < pagination.last_page">' +
'<a href="#" aria-label="Next" #click.prevent="changePage(pagination.current_page + 1)">' +
'<span aria-hidden="true">»</span>' +
'</a>' +
'</li>' +
'</ul>' +
'</nav>',
props: ['user'],
data: function() {
return {
pagination: {
total: 0,
per_page: 2,
from: 1,
to: 0,
current_page: 1
},
offset: 4,
}
},
computed: {
isActived: function () {
return this.pagination.current_page;
},
pagesNumber: function () {
if (!this.pagination.to) {
return [];
}
var from = this.pagination.current_page - this.offset;
if (from < 1) {
from = 1;
}
var to = from + (this.offset * 2);
if (to >= this.pagination.last_page) {
to = this.pagination.last_page;
}
var pagesArray = [];
while (from <= to) {
pagesArray.push(from);
from++;
}
return pagesArray;
}
},
ready : function(){
this.getUsers(this.pagination.current_page);
},
methods : {
getUsers: function(page){
this.$http.get('/user/api?page='+page).then((response) => {
this.$set('pagination', response.data);
});
},
changePage: function (page) {
this.pagination.current_page = page;
this.getUsers(page);
}
}
})
Vue.component('vue-pagination', VueComponent);
new Vue({
el: '#users',
data: {
users: [],
pagination: {
total: 0,
per_page: 2,
from: 1,
to: 0,
current_page: 1
},
offset: 4,
},
ready : function(){
this.getUsers(this.pagination.current_page);
},
methods : {
getUsers: function(page){
this.$http.get('/user/api?page='+page).then((response) => {
this.$set('users', response.data.data);
});
},
}
});
How to make this pagination work with vue js when using vue component Please Help me.
It is not that complicated. You just forgot to link your current page with your component. To do so , just change your code in HTML section
<vue-pagination></vue-pagination>
to
<vue-pagination :pagination="pagination" v-on:click="getUsers(pagination.current_page)"></vue-pagination>
In your js code , get rid of data function from VueComponent and add pagination props
.....
props: {
pagination: {
type: Object,
required: true
}
},
computed: {
pagesNumber: function () {
if (!this.pagination.to) {
......
Also, remove your getUsers method from VueComposent and combine with getUsers method in Vue main instance
getUsers: function(page){
this.$http.get('/user/api?page='+page).then((response) => {
this.$set('users', response.data.data);
this.$set('pagination', response.data);
});
I think, now your code should work as expected.
Related
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.
I have a menu with some post categories:
<ul>
#foreach($categories->get() as $category)
<li class="ative">
{{$category->name}}
</li>
#endforeach
</ul>
When I click in the category, for example with id "1", through the menu I want to show the posts that belong to the category with id "1"in the "#posts" div.
So, the #posts div shows the last posts when the page is acessed at first, but after a category is clicked it should show the posts that belong to the clicked category. So I have the #posts div:
<div id="posts">
#foreach($posts as $post)
<div id="posts">
<img src="{{$post->image}}">
<h1>{{$post->title}}</h1>
<!-- ... -->
</div>
#endforeach
</div>
If the category with id "1" is clicked in the console appears the info of the only post that exist for now for that category with id "1":
{id: 1, title: "Title", description: "", …}
Now do you know how to show in the #posts div the posts that belong to the clicked category with the append method? Something like below (but like below dont works):
$('#posts').append(
<div id="posts">
<img src="{{$post->image}}">
<h1>{{$post->title}}</h1>
</div>);
});
I have a FrontController index method that shows the homepage:
public function index(){
return view('home')
->with('categories', Category::orderBy('created_at', 'desc')->get())
->with('posts', Post::orderBy('created_at','desc')->get());
}
I also have a PostController that has a method postsFromCategory to get the posts from a selected category:
public function WhereHasCategory(Request $request)
{
$posts = Post::whereHas('categories', function ($categories) use (&$request) {
$categories->where('category_post.id',$request->id);
})->get();
return response()->json($posts);
}
Then in the index.blade.php I have the ajax:
$.ajax({
url: '{{ route('category.posts',null) }}/' + category_id,
type: 'GET',
success:function(result){
$('#posts').empty();
$.each(result, function(index, post) {
newPosts += '<img src="' + post.image + '">' +
+ '<h1>' + post.title + '</h1>';
});
console.log(result);
},
error: function(error) {
console.log(error.status)
}
});
I have never coded in laravel so the syntax is going to be off, but I hope the gist sticks:
First, you should not use duplicate IDs like "posts". Try assigning "post" + $key to every div inside the foreach:
<div id="posts">
#foreach($posts as $key => $post)
<div id="post" + $key>
<img src="{{$post->image}}">
<h1>{{$post->title}}</h1>
<!-- ... -->
</div>
#endforeach
</div>
Now, if you are retrieving the post per category with this code:
$.each(result, function(index, post) {
newPosts += '<img src="' + post.image + '">' +
+ '<h1>' + post.title + '</h1>';
});
you could try:
var newPosts = "";
$.each(result, function(index, post) {
newPosts += '<img src="' + post.image + '">' +
+ '<h1>' + post.title + '</h1>';
});
$('#posts').html(newPosts);
let me know
Change id to class
<div class="posts">
#foreach($posts as $post)
<div id="posts">
<img src="{{$post->image}}">
<h1>{{$post->title}}</h1>
<!-- ... -->
</div>
#endforeach
</div>
The code $('#posts').append() is not needed since we can add it in success callback of ajax.
Chenge the ajax function to this
$.ajax({
url: '{{ route('category.posts') }}',
type: 'GET',
data : { id:category_id },
success:function(result){
$('#posts').empty();
var newPosts='';
$.each(result, function(index, post) {
newPosts += '<img src="' + post.image + '">' +
+ '<h1>' + post.title + '</h1>';
});
$('#posts').html(newPosts);
},
error: function(error) {
console.log(error.status)
}
});
I'm beginner in DataTables or dev in general :)
I use Laravel 5.4 and several DataTables which get their data using ajax calls requests and everything it's working just fine :) .
One of the tables have a column with a hyperlink on it I need to send further in the hyperlink an external variable which is not returned by Ajax response but it's hidden in same form with the table.
So, I have the table definition:
$('#tabelClientiOferta').DataTable({
lengthMenu: [[15, 25, 100, -1], [15,25, 100, "All"]],
processing: true,
serverSide: true,
ajax: 'ajaxClienti',
columns: [
{data:'id',name:'id' , sClass: "hidden", "bSearchable": false },
{data: 'denumire', name: 'denumire',
"fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
$(nTd).html("<a href='selectieFurnizor?idClient=" + oData.id + "'>" + oData.denumire + "</a>")
}
},
{ data: 'cui', name: 'cui' },
{ data: 'telefon', name: 'telefon', "bSearchable": false},
{ data: 'email', name: 'email', "bSearchable": false },
]
});
Controller function which respond to ajax call:
public function clienti(Request $request)
{
return Datatables::of(DB::table('clienti')->get(['id','denumire','cui','telefon','email']))->make(true);
}
HTML template with table and hidden variable:
#extends ('master')
#section('content')
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="tabelOferte" style ="width: 900px">
<table id = "tabelClientiOferta" class="table table-responsive table-striped table-hover">
<thead >
<tr style="font-weight: bold" >
<td>id</td>
<td>Denumire</td>
<td>CUI</td>
<td>Telefon</td>
<td>Email</td>
</tr>
</thead>
</table>
</div>
<input id = "hiddenId" name="hiddenId" type="text" value = {{$someId}} hidden />
</div>
</div>
</div>
#stop
So I need to pass the hidden variable as the second parameter to the "denumire" column hyperlink, something like:
$(nTd).html("<a href='selectieFurnizor?idClient=" + oData.id + "&hiddenId="+$('#hiddenId') "'>" + oData.denumire + "</a>")
.
Is that possible?
The solution which I use now is to return a view from the controller and include in it a static DataTable (with data already prepared and sent by the controller).
Thank you for your attention
:)
Server-side: use add coloumn from controller
$data = DB::table('clienti')->get(['id','denumire','cui','telefon','email']);
return Datatables::of($data)
->addColumn('clear', function ($data) {
return '<i class="glyphicon glyphicon-trash"></i> Clear';
})
->escapeColumns([])
->make(true);
And add to columns with initial js of datatables
{data: 'clear', name: 'cleat', orderable: false, searchable: false }
or use js based columns render() function, official doc and examples here: https://datatables.net/reference/option/columns.render
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
}
});
I have a Symfony app which allows CRUD operations on some events and also searching for them. The problem I get is when trying to get the results I'm searching for displayed without refreshing the page. It's the first time I'm using ajax and I think it's something wrong with the function. When I search for a word in any event name, the page is not refreshing and it shows undefined instead of showing the entries.
I appreciate any help!
Here's the method from the Controller:
public function ajaxListAction(Request $request){
//fetch the data from the database and pass it to the view
$em = $this->getDoctrine()->getManager();
$searchTerm = $request->get('search');
$form = $this->createFormBuilder()
->add('search', SubmitType::class, array('label' => 'Search', 'attr' => array('class' => 'btn btn-primary', 'style' => 'margin-bottom:15px')))->getForm();
$organizer = array();
if($searchTerm == ''){
$organizer = $this->getDoctrine()->getRepository('AppBundle:Organizer')->findAll();
}
elseif ($request->getMethod() == 'GET') {
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
$organizer = $em->getRepository('AppBundle:Organizer')->findAllOrderedByName($searchTerm);
}
$response = new JsonResponse();
$results = array();
foreach ($organizer as $value) {
$results[] = json_encode($value);
}
return $response->setData(array(
'results' => $results
));
}
and here's the script for the search:
$(document).ready( function(event) {
$("#search").submit(function(event) {
event.preventDefault(); //prvent default submission event
$form = $(this);
var data = $('#search_term').val();
$.ajax({
url: '/ajax',
type: "GET",
data: {'search' : data },
success: function(response){
var output = '';
for (var i = 0; i < response.length; i++) {
output[i] = output + response;
}
$('#ajax_results').html('<tr><td>' + response.id + '</td></tr>' + '<tr><td>' + response.name + '</td></tr>' + '<tr><td>' + response.dueDate + '</td></tr>');
}
})
});
});
and the index.html.twig file for displaying the data:
{% extends 'base.html.twig' %}
{% block body %}
<h2 class="page-header"> Latest events </h2>
<form id="search" method="GET" action="">
<input type="text" name="search" id="search_term" />
<input type="submit" name="submit" value="Search" />
</form>
<hr />
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Event</th>
<th>Due Date</th>
<th></th>
</tr>
</thead>
<tbody id="ajax_results">
{% for Events in organizer %}
<tr>
<th scope="row">{{Events.id}}</th>
<td>{{Events.name}}</td>
<td>{{Events.dueDate|date('j F, Y, g:i a')}}</td>
<td>
View
Edit
Delete
</td>
</tr>
{% endfor %}
<table class="table table-striped">
{% if organizer|length > 0 %}
{% for items in organizer %}
{% endfor %}
{% else %}
<tr>
<td colspan="2">No matching results found!</td>
</tr>
{% endif %}
</table>
</tbody>
</table>
{% endblock %}
Lets try to refactor your code first. Perhaps it will bring you near the solution.
public function ajaxListAction(Request $request){
$searchTerm = $request->get('search');
//don't need form here
if($searchTerm == ''){
$organizer = $this->getDoctrine()->getRepository('AppBundle:Organizer')->findAll();
}else{
//repository should search by searchterm in next step
$organizer = $this->getDoctrine()->getRepository('AppBundle:Organizer')->findAllOrderedByName($searchTerm);
}
return new JsonResponse($organizer);
}
and javascript:
$(document).ready( function(event) {
$("#search").submit(function(event) {
event.preventDefault(); //prvent default submission event
$form = $(this);
var data = $('#search_term').val();
$.ajax({
url: '/ajax',
type: "GET",
data: {'search' : data },
success: function(response){
$('#ajax_results').html('');
$.each(response, function(key, value) {
console.log(key, value);
$('#ajax_results').append('<tr><td>' + response[key].id + '</td></tr>' + '<tr><td>' + response[key].name + '</td></tr>' + '<tr><td>' + response[key].dueDate + '</td></tr>');
});
}
})
});
});
Please tell what do you see in js console after submit the search?
I managed to make it work. The problem was that I didn't have all the fields sent into the array in the jsonSerialize() method in the Entity file and thus the fields were showing undefined.
I also completed the append method in the .js file in order to have the whole markup replicated upon the ajax call.
Thanks to Rawburner for the suggestions!