How to implement search functionality with Laravel lighthouse-php and vuejs? - php

Backend Laravel with scout and algolia search, Lighthouse-php
Below laravel grapql:
products(search: String #search, orderBy: _ #orderBy(columns: ["created_at"])): [Product!]! #paginate
Graphql-playground search work perfectly:
products(first: 5, search: $searchText) {
data {
id
name
description
}
paginatorInfo {
currentPage
lastPage
}
}
}
Vue template need advice how to complete my code with search functionality?:
<template>
<div class="py-16 px-16 text-gray-800">
<div>
Search
<input v-model="search" type="search" />
</div>
<div v-for="product in products" :key="product.slug">
?????
</div>
</div>
</template>
<script>
import ALL_PRODUCTS from '#/graphql/AllProducts.gql'
export default {
apollo: {
products: {
fetchPolicy: 'network-only',
query: ALL_PRODUCTS,
variables() {
return {
searchText: this.search,
}
},
skip() {
return !this.search
},
},
},
data() {
return {
search: '',
}
},
head: {
title: 'Products',
},
}
</script>
Please advice. Thank you!

Finally resolve my issue:
<div class="py-16 px-16 text-gray-800">
<div>
Search
<input v-model="search" type="search" #input="searchResults()" />
</div>
<div v-if="products">
<div v-for="product in products.data" :key="product.slug">
<NuxtLink
:to="{ name: 'products-slug', params: { slug: product.slug } }"
>{{ product.name }}</NuxtLink
>
</div>
</div>
</div>
</template>
<script>
import ALL_PRODUCTS from '#/graphql/AllProducts.gql'
export default {
apollo: {
products: {
fetchPolicy: 'network-only',
query: ALL_PRODUCTS,
variables() {
return {
searchText: this.search,
}
},
skip() {
return !this.search
},
},
},
data() {
return {
search: '',
}
},
methods: {
searchResults() {
return this.products
},
},
head: {
title: 'Products',
},
}
</script>

Related

Search by Date and show data in BootstrapTable

What I want to do is to input some date time range and show me the data in a BootstrapTable. I am not able to do it.
I have two php files one is my WebSite and the other is the MySql query.
So this where I load the Input data fields and my BootstrapTabel:
<div class='col-md-2 float-left'>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">Datum von:</span>
</div>
<input id="dateVon" name="dateVon" value="2022-01-01" type="text" class="form-control" placeholder="2022-01-01" aria-describedby="dateVon">
</div>
</div>
<div class='col-md-2 float-left'>
<div class="input-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">Datum bis:</span>
</div>
<input id="dateBis" name="dateBis" value="2022-01-31" type="text" class="form-control" placeholder="2022-01-31" aria-describedby="dateBis">
</div>
</div>
</div>
<button id="remove" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#deleteModal" disabled>
<i class="bi bi-trash"></i> Delete
</button>
<button id="refresh" class="btn btn-primary btn-sm" onclick="refreshFunction(dateVon,dateBis);">
<i class="bi bi-trash"></i> Refresh
</button>
</div>
<div class="card-body">
<table id="table"
data-toolbar="#table-responsive"
data-search="true"
data-show-refresh="true"
data-show-toggle="true"
data-show-fullscreen="true"
data-show-columns="true"
data-show-columns-toggle-all="true"
data-detail-view="true"
data-show-export="true"
data-click-to-select="true"
data-detail-formatter="detailFormatter"
data-minimum-count-columns="2"
data-pagination="true"
data-id-field="ID"
data-page-size="50"
data-page-list="[50, 100, all]"
data-show-footer="true"
data-side-pagination="client"
data-url="verpAnrufData.php"
data-response-handler="responseHandler"
data-detail-view="true">
</table>
<script>
var $table = $('#table')
var $remove = $('#remove')
var selections = []
function getIdSelections() {
return $.map($table.bootstrapTable('getSelections'), function(row) {
return row.ID
})
}
function responseHandler(res) {
$.each(res.rows, function(i, row) {
row.state = $.inArray(row.ID, selections) !== -1
})
return res
}
function totalTextFormatter(data) {
return 'Total'
}
function totalNameFormatter(data) {
return data.length
}
function totalPriceFormatter(data) {
var field = this.field
return '$' + data.map(function(row) {
return +row[field].substring(1)
}).reduce(function(sum, i) {
return sum + i
}, 0)
}
function initTable() {
$table.bootstrapTable('destroy').bootstrapTable({
locale: 'de-DE',
columns: [{
field: 'state',
checkbox: true,
rowspan: 1,
align: 'center',
valign: 'middle'
}, {
field: 'id',
title: 'ID',
rowspan: 1,
align: 'center',
valign: 'middle',
sortable: true,
footerFormatter: totalTextFormatter
}, {
field: 'name',
title: 'Kunde',
sortable: true,
align: 'left',
footerFormatter: totalNameFormatter
}, {
field: 'callerid',
title: 'Anrufer',
sortable: true,
align: 'left'
}, {
field: 'datetime_entry_queue',
title: 'DatumZeit',
sortable: true,
align: 'left'
}, {
field: 'duration_wait',
title: 'Warteschleife (sec)',
sortable: true,
align: 'left'
}]
})
$table.on('check.bs.table uncheck.bs.table ' +
'check-all.bs.table uncheck-all.bs.table',
function() {
$remove.prop('disabled', !$table.bootstrapTable('getSelections').length)
//$btnEdit.prop('disabled', !$table.bootstrapTable('getSelections').length)
// save your data, here just save the current page
selections = getIdSelections()
// push or splice the selections if you want to save all data selections
})
$table.on('all.bs.table', function(e, name, args) {
console.log(name, args)
})
}
$(function() {
initTable()
$('#locale').change(initTable)
})
function refreshFunction() {
var data = {
dateVon: $("input[id='dateVon']").val(),
dateBis: $("input[id='dateBis']").val()
};
$.ajax({
method: "post",
url: "verpAnrufData.php",
data: data,
success: function(response) {
/* console.log(data); */
/* params.success({
"rows": data,
"total": data.length
}, null, {}); */
//initTable();
$table.bootstrapTable('refresh')
}
})
}
and this is my MySql php file:
<?php
include "dbConn.php";
$dateVon = $_POST["dateVon"];
$dateBis = $_POST["dateBis"];
$sqltran = mysqli_query($db, "SELECT ce.id,
ce.callerid,
ce.datetime_entry_queue,
ce.duration_wait,
convert(cast(convert(cae.name using latin1) as binary) using utf8) name
FROM call_center.call_entry ce, call_center.campaign_entry cae
WHERE ce.id_campaign = cae.id
AND datetime_entry_queue BETWEEN '$dateVon 00:00:00' AND '$dateBis 23:59:59'
AND status = 'abandonada'
ORDER BY name, datetime_entry_queue ASC;");
$count = mysqli_num_rows($sqltran) ;
$arrVal = array();
$i=1;
while ($rowList = mysqli_fetch_array($sqltran)) {
$name = array(
'id' => $rowList['id'],
'name'=> $rowList['name'],
'callerid'=> $rowList['callerid'],
'datetime_entry_queue'=> $rowList['datetime_entry_queue'],
'duration_wait'=> $rowList['duration_wait'],
);
array_push($arrVal, $name);
$i++;
}
$allData = array(
'total' => $count,
'rows' => $arrVal,
);
echo json_encode($allData);
mysqli_close($db); // close connection
If i harde code the Dates in this file like this:
$dateVon = "2022-01-01";
$dateBis = "2022-12-31";
Then I can see the data, but then I am not able to input another dates and refresh it.
I am desperate I can not make it work, pls help. :)
I have found the answer of my problem, it was in the ajax function and the way I was responding the cell. Thx KIKO Software for the sugesstion.
function refreshFunction() {
$.ajax({
method: "POST",
dataType: "json",
url: "verpAnrufData.php",
data: {
dateVon: $("input[id='dateVon']").val(),
dateBis: $("input[id='dateBis']").val()
},
success: function(response) {
console.log(response);
$table.bootstrapTable('load',{
"rows": response,
"total": response.length
}, null, {});
}
})
};

I can't understand how the destroy function work here?

I am working on old laravel project and I have to modify existing one. So I am now trying to understand the code. The project is on laravel and yajra datatable. I can't understand how the destroy function work ? In the view there is a no call for destroy function but when I click the delete button still it is working.
Controller
public function loadSizes()
{
$sizes = Size::select(['id', 'name', 'code'])->get();
return DataTables::of($sizes)
->addColumn('action', function ($size) {
return '<i class="fa fa-wrench" aria-hidden="true"></i>
<button type="button" data-id="' . $size->id . '" class="btn btn-default remove-size remove-btn" data-toggle="tooltip" data-placement="top" title="Delete"><i class="fas fa-trash-alt" aria-hidden="true"></i></button>';
})
->rawColumns(['action'])
->make(true);
}
public function destory(Request $request)
{
$result = Size::where('id', $request->input('size_id'))->delete();
if ($result) {
return "SUCCESS";
} else {
return "FAIL";
}
}
view
#extends('layouts.sidebar')
#section('content')
<div class="row">
<div class="col-sm-12 pad-main">
<div class="row">
<div class="col-md-6">
<h4 class="cat-name"> Size List</h4>
</div>
</div>
<div class="row">
<div class="col-md-12 table-responsive pad-tbl">
<table class="table table-striped" id="size_table">
<thead>
<tr>
<th scope="col"> Name</th>
<th scope="col"> Code</th>
<th scope="col"> Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
#if (Session::has('action'))
#if (Session::get('action') == "create")
#if (Session::has('status_success'))
<script > showAlert("SUCCESS", "Size creation successful");</script >
#elseif(Session::has('status_error')))
<script > showAlert("FAIL", "Size creation fail");</script >
#endif
#elseif(Session::get('action') == "update")
#if (Session::has('status_success'))
<script > showAlert("SUCCESS", "Size update successful");</script >
#elseif(Session::has('status_error')))
<script > showAlert("FAIL", "Size update fail");</script >
#endif
#endif
#endif
<script>
$(document).ready(function () {
$('#size_table').DataTable({
language: {
searchPlaceholder: "Search records"
},
"columnDefs": [
{"className": "dt-center", "targets": "_all"}
],
processing: true,
serverSide: true,
ajax: '{!! url(' / load - sizes') !!}',
columns: [
{data: 'name', name: 'name'},
{data: 'code', name: 'code'},
{data: 'action', name: 'action'},
]
});
});
$(document.body).on("click", ".remove-size", function () {
var size_id = $(this).data('id');
showConfirm("DELETE", "Do you want to delete this Size ?", "deleteSize(" + size_id + ")");
});
function deleteSize(id) {
$.ajax({
type: 'get',
url: '{!! url('delete-size') !!}',
data: {size_id: id},
success: function (data) {
if (data == "SUCCESS") {
$('[data-id="' + id + '"]').closest('tr').remove();
showAlert("SUCCESS", "Delete Size successful");
}
}, error: function (data) {
showAlert("FAIL", "Delete Size fail");
}
});
}
</script>
#endsection
At the bottom of the blade view there is an AJAX in function destory(id).
That AJAX is sending a GET request to a URL delete-size with size id.
Now, if you search your web.php file for that URL (location - routes/web.php), you'll find something like this:
Route::get('delete-size', 'SizeController#destory');
This route would be sending the size id to your destory function, which is in turn searching the Size in your DB and deleting it.
// Controller
public function destroy($id)
{
Tag::find($id)->delete();
Toastr::success('Tag Successfully Deleted',"Success");
return redirect()->back();
}
// Route
Route::group(['as'=>'admin.','prefix'=>'admin','namespace'=>'Admin','middleware'=>['auth','admin']], function (){
Route::resource('tag','TagController');
});
// HTML file
<form id="delete-form-{{ $tag->id }}" action="{{ route('admin.tag.destroy',$tag->id) }}" method="POST" style="display: none;">
#csrf
#method('DELETE')
</form>

laravel vue.js The GET method is not supported for this route. Supported methods: POST

I am creating commenting system. Now, I want to post a new comment, but when I send a comment, I got an error in http://127.0.0.1:8000/comments/51.
The GET method is not supported for this route. Supported methods:
POST.
I want to post a comment in this URL http://127.0.0.1:8000/results/51.
In my chrome dev tool console, I have this error
Failed to load resource: the server responded with a status of 500
(Internal Server Error)
web.php
Route::middleware(['auth'])->group(function(){
//post a comment
Route::POST('comments/{post}', 'CommentController#store')->name('comment.store');
});
//comment area
Route::get('results/{post}/comments', 'CommentController#index');
Route::get('comments/{comment}/replies', 'CommentController#show');
comments.vue
<template>
<div class="commentarea" >
<div class="comment-posts" >
<div v-if="!auth" class="user-comment-area" >
<div class="user-post">
<!---<img src="{{asset('people/person7.jpg')}}" class="image-preview__image">--->
<input v-model="newComment" type="text" name="comment">
</div>
<div class="comments-buttons">
<button class="cancel-button">Cancel</button>
<button #click="addComment" class="comment-button" type="submit">Comment</button>
</div>
</div>
<h4>Comments ()</h4>
<div class="reply-comment" v-for="comment in comments.data" :key="comment.id">
<div class="user-comment">
<div class="user">
<!---<img src="{{ $comment->user->img }}" class="image-preview__image">--->
<avatar :username="comment.user.name"></avatar>
</div>
<div class="user-name">
<span class="comment-name">{{ comment.user.name }}</span>
<p>{{ comment.body }}</p>
</div>
</div>
<div class="reply">
<button class="reply-button">
<i class="fas fa-reply"></i>
</button>
</div>
<replies :comment="comment"></replies>
</div>
</div>
<div>
<button v-if="comments.next_page_url" #click="fetchComments" class="load">Load More</button>
</div>
</div>
</template>
<script>
import Avatar from 'vue-avatar'
import Replies from './replies.vue'
export default {
props: ['post'],
components: {
Avatar,
Replies
},
mounted() {
this.fetchComments()
},
data: () => ({
comments: {
data: []
},
newComment: '',
auth: ''
}),
methods: {
fetchComments() {
const url = this.comments.next_page_url ? this.comments.next_page_url : `/results/${this.post.id}/comments`
axios.get(url).then(({ data }) => {
this.comments = {
...data,
data: [
...this.comments.data,
...data.data
]
}
})
.catch(function (error) {
console.log(error.response);
})
},
addComment() {
if(! this.newComment) return
axios.post(`/comments/${this.post.id}`, {
body: this.newComment
}).then(( {data} ) => {
this.comments = {
...this.comments,
data: [
data,
...this.comments.data
]
}
})
}
}
}
</script>
commentsController.php
public function store(Request $request, Post $post)
{
return auth()->user()->comments()->create([
'body' => $request->body,
'post_id' => $post->id,
'comment_id' => $request->comment_id
])->fresh();
}
comment.php
protected $appends = ['repliesCount'];
public function post()
{
return $this->belongsTo(Post::class);
}
public function getRepliesCountAttribute()
{
return $this->replies->count();
}
I am glad if someone helps me out.
your URL is : http://127.0.0.1:8000/results/51.
your routes should be :
Route::group(['middleware' => 'auth'],function () {
Route::post('comments/{post_id}', 'CommentController#store')->name('comment.store');
});
your controller will be :
public function store(Request $request,$post_id)
{
return auth()->user()->comments()->create([
'body' => $request->body,
'post_id' => $post_id,
'comment_id' => $request->comment_id
])->fresh();
}
Thank you, I put catch method, and the issue was I did not include protected $fillable ['body','post_id', 'comment_id'] in comment model.

why vue component say there is not a variable in data?

this is my Axios component
<template>
<div>
<div class="comment">
<div class="body">
<p>{{fulluser.name}}</p>
</div>
<img class="image" :src="userimg" alt="" width="50px" height="50px">
</div>
</div>
</template>
<script>
import axiosRetry from 'axios-retry';
export default {
name: "commentcomponent",
props:
[
"comment"
],
data()
{
return{
fulluser:null
}
},
computed:
{
userimg()
{
return "/images/"+this.fulluser.image;
}
},
created() {
// axiosRetry(axios, { retries: 5 });
axios.get("/comment/userimage/"+this.comment.id)
.then(res=>
{
this.fulluser=res.data;
console.log(this.fulluser.id)
})
},
methods:
{
userimg()
{
return "/images/"+this.fulluser.image;
}
}
}
</script>
when I open the browser it works correctly but when I inspect it give me this error
app.js:44975 [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of null"
but it works in the browser and it gives me all images and names
how can I fix this?
Calling axios is asynchronous. That means the component is rendered before initializing fulluser value.
So you need to consider when fulluser is null even though it may be a short period.
<p>{{fulluser && fulluser.name || ''}}</p>
Or
data()
{
return{
fulluser: {
name: ''
}
}
},

Making a table with vue-js and Laravel

I'm in the beginning of learning laravel and vue-js, so this is rather difficult to me. I want to make a component in vue-js with a table, with sorting and pagination.
When I started the project I only used Laravel and jquery, so now I'm turning to vue js and it's getting complicated. What I have is this:
In my index.blade.php
#extends('layouts.dashboard')
#section('content')
<div class="container">
<div class="row">
<div class="col">
<table class="table">
<thead>
<tr>
<th> #sortablelink('first_name','First name') </th>
<th> #sortablelink('last_name', 'Last name') </th>
<th> #sortablelink('email', 'E-mail address') </th>
<th> #sortablelink('created_at', 'Creation date') </th>
<th></th>
</tr>
</thead>
<tbody is="submissions"></tbody>
</table>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col">
{{ $submissions->appends(\Request::except('page'))->render() }}
<div class="total-submissions">
Total submissions:
{{ $submissions->firstItem() }}-{{ $submissions->lastItem() }} of {{ \App\Submission::count() }}
</div>
</div>
</div>
</div>
#stop
In my component Submissions.vue:
<template>
<tbody>
<tr v-for="submission in submissions" :key="submission.id">
<td> {{submission.first_name}}</td>
<td> {{submission.last_name}} </td>
<td> {{submission.email}} </td>
<td> {{submission.created_at}} </td>
<td>
<a class="btn btn-default btn-primary" id="btn-view"
:href="'/dashboard/submissions/' + submission.id">View</a>
<a class="btn btn-default btn-primary"
id="btn-delete"
:href="'/dashboard/submissions'"
#click.prevent="deleteSubmission(submission)">Delete</a>
<label class="switch">
<input class="slider-read" name="is_read"
v-model="submission.is_checked"
#change="updateCheckbox(submission)"
type="checkbox">
<span class="slider round"></span>
</label>
</td>
</tr>
</tbody>
</template>
<script>
import qs from 'qs';
import axios from 'axios';
export default {
data: function () {
return {
submissions: [],
}
},
beforeCreate() {
},
created() {
},
mounted() {
this.fetch();
},
methods: {
fetch: function () {
let loader = this.$loading.show();
var queryString = window.location.search;
if (queryString.charAt(0) === '?')
queryString = queryString.slice(1);
var args = window._.defaults(qs.parse(queryString), {
page: 1,
sort: 'id',
order: 'asc'
});
window.axios.get('/api/submissions?' + qs.stringify(args)).then((response) => {
loader.hide();
this.submissions = response.data.data
});
},
deleteSubmission(submission) {
this.$dialog.confirm("Are you sure you want to delete this record?", {
loader: true
})
.then((dialog) => {
axios.delete('api/submissions/' + submission.id)
.then((res) => {
this.fetch()
})
.catch((err) => console.error(err));
setTimeout(() => {
console.log('Delete action completed');
swal({
title: "Update Completed!",
text: "",
icon: "success",
});
dialog.close();
}, 1000);
})
.catch(() => {
console.log('Delete aborted');
});
},
updateCheckbox(submission)
{
this.$dialog.confirm("Are you sure?", {
loader: true
})
.then((dialog) => {
axios.put('/api/submissions/' + submission.id, submission,
)
.then(function (response) {
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
setTimeout(() => {
console.log('Action completed');
dialog.close();
swal({
title: "Update Completed!",
text: "",
icon: "success",
});
}, 0);
})
.catch(() => {
submission.is_checked === false ? submission.is_checked = true : submission.is_checked = false;
console.log('Aborted');
});
},
}
}
</script>
Now what I want to accomplish: Put everything in the component, but since I have php in the table to sort everything how can I do this in vue? I'm trying with bootstrap vue tables, but I'm not sure if I can display data like this. Thanks in advance.

Categories