Search in vuejs with laravel backend api - laravel

I'm using laravel 5.6 as the api for the backend and vuejs for the frontend spa application. And https://github.com/nicolaslopezj/searchable package for search which worked well in my previous projects where i used blade templating engine.
I'm new to vuejs and im learning how to do things and im stuck at a point where im confused how to use laravel search on the frontend.
What i did previously in other projects where i used blade for the frontend
In my controller
public function index(Request $request)
{
$start_search = microtime('s');
$searchterm = $request->input('search');
if($request->has('search')){
$results = Web::search($searchterm)->paginate(10);
} else {
$results = Web::latest()->paginate(10);
}
$stop_search = microtime('s');
$time_search = ($stop_search - $start_search);
return view('search.index', compact('results', 'searchterm', 'time_search'));
}
And in my view
<small>{{$results->total()}} results found for "<em class="b-b b-warning">{{$searchterm}}</em>" in {{$time_search}} seconds</small>
#forelse ($results as $result)
<div class="mb-3">
{{$result->meta_title}} <span class="badge badge-pill primary">{{$result->rank}}</span>
<span class="text-success clear h-1x">{{$result->url}}</span>
<span class="h-2x">{{$result->meta_description}}</span>
</div>
#empty
No Results Found
#endforelse
<div class="pt-2 pagination-sm">
{{ $results->links('vendor.pagination.bootstrap-4') }}
</div>
This code worked well where i was able to search and display results properly along with search time.
Now i want to do the same with laravel api and vuejs frontend. So this is what i tried
public function index(Request $request)
{
$start_search = microtime('s');
$searchterm = $request->input('search');
if($request->has('search')){
$results = Web::search($searchterm)->paginate(10);
} else {
$results = Web::latest()->paginate(10);
}
$stop_search = microtime('s');
$time_search = ($stop_search - $start_search);
return WebResource::collection($results);
}
I created a collection resource for the same.
Question 1. My question related to controller code, how to return $searchterm and $time_search so that i can use them on the frontend.
In my vue component, i tried with my learning till now
<template>
other code..
<div class="mb-3" v-for="result in results" :key="result.results">
<router-link :to="result.url" class="text-primary clear h-1x"> {{ result.meta_title }} </router-link>
<span class="h-2x">{{ result.meta_description }}</span>
</div>
</template>
<script>
import axios from 'axios'
import { mapGetters } from 'vuex'
export default {
layout: 'main',
computed: mapGetters({
locale: 'lang/locale',
authenticated: 'auth/check'
}),
metaInfo () {
return { title: this.$t('searchpagetitle') }
},
data: function () {
return {
results: [],
title: window.config.appName
}
},
watch: {
locale: function (newLocale, oldLocale) {
this.getResults()
}
},
mounted() {
console.log(this.locale)
this.getResults ()
},
methods: {
getResults() {
var app = this;
axios.get('/api/web')
.then(response => {
// JSON responses are automatically parsed.
this.results = response.data.data
})
.catch(e => {
this.errors.push(e)
})
}
}
}
</script>
Question 2: My second question related to vuejs, how to create a search form and render results according to the search and with proper search url ending with ?searchterm=searchkeywords in my case.
When i used blade i used the normal html form with action url so that it rendered results. Also i used $searchterm to use the same search terms to search in other routes like images, videos.
I just used {{ url('/images?searchterm='.$searchterm) }} in the href so that when user clicks on it, it renders results of all images with the same keyword just like google. And also used placeholder as "enter your search" and value as "{{$searchterm}}" so that the search term stayed in the search form too.
I want to know how to do all the same in vuejs.
Thank you

It is better to append the search keyword in request URL of API in frontend. So your request url will be like
axios.get('/api/web?searchterm='+this.searchterm)
And in your Laravel controller, you can get this value by using Input::get() , so your code to get searchterm will be
$searchterm = Input::get('searchterm');
And then you can fetch your data on basis of $searchterm variable.

Related

Vue js with laravel not geting api data and response

this is Vue js component please help me to get data in template. getting data from vue js api in console i got undefined. Not getting blogList Data please help to get blog list data.
my api is correct and fetch data.
<template>
<div v-for="blog in blogList">
Hii i am {{ blog.name }} , {{ blog.mail }}
</div>
</template>
<script>
import ApiRequest from "../../js/api-request";
export default {
data() {
return {
blogList: '',
};
},
created() {
const request = new ApiRequest('/api/blog/list', (blogList) => {
this.blogList = blogList;
console.log(blogList);
}, () => {
//
});
request.get();
}
};
</script>

Cannot read properties of null (reading 'allowRecurse')

I have a problem with Laravel/Inertia which gets me the error message :
Cannot read properties of null (reading 'allowRecurse')
There is a form, i post the form to a controller and after saving the data i tried to redirect to the main page. I tried several ways, return Redirect::route('home'); or return redirect()->back(); even other ways i found searching for a solution. They all give me the same error message.
The redirect()->back() function works and brings me back to my form, but when i try to redirect there i get that same message.
I deleted everything of what i think is not essential, so the form and controller now don't do anything anymore, but still i get that error message.
I can't find anything about this error on the internet. What mistake am I overlooking?
Edit: I found something... Somewhere in page that i am going to (that home.vue page) i have a link with the same URL as where i came from. Apparently Vue or Laravel doesn't approve. But i need that. Can i set the value of AllowRecurse to True somewhere? Or is that a bad idea?
My vue-file:
<template>
<div>
<form #submit.prevent="submit">
<div class="flex justify-center mt-4">
<app-button class="w-1/2 justify-center" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
Insturen
</app-button>
</div>
</form>
</div>
</template>
<script>
import AppButton from '#/Components/Button.vue'
export default {
components: {
AppButton,
},
props: {
game_id: String,
code: String,
},
data() {
return {
form: this.$inertia.form({
name: '',
email: '',
})
}
},
setup() {
},
methods: {
submit() {
this.form.post(route('toto_store',{'game_id': this.game_id, 'code': this.code}), {
preserveScroll: true,
resetOnSuccess: false,
onSuccess: () => { this.$inertia.visit(route('home'))} ,
});
}
}
}
</script>
My controller:
namespace App\Http\Controllers;
use Inertia\Inertia;
use App\Models\Guess;
use Illuminate\Http\Request;
class TotoController extends Controller
{
public function store(Request $request, $id, $code)
{
return redirect()->back()->with("success", "Opgeslagen");
}
}
My webroutes:
Route::get('/', [HomeController::class, 'show'])->name('home');
Route::get('/guesses/{game_id?}', [GuessController::class, 'index'])->name('guesses');
Route::get('/toto/{game_id}/{code}', [TotoController::class, 'create'])->name('toto_create');
Route::post('/toto/{game_id}/{code}', [TotoController::class, 'store'])->name('toto_store');
Route::get('/qr-code/{id}', [QRController::class, 'show'])->name('qr-code');
The error:
Any ideas?

Front End File Upload using Vue and Winter Cms

I'm trying to upload images from a Vue frontend via Illuminate/Http/Request to WinterCMS.
Vue finds the file and i can console.log the File object, but I'm unsure how to get this over the api. for example I've tried
public function saveImage(Request $req){
$images = $req->files('images');
}
which doesn't work, nor does
public function saveImage(Request $req){
$images = $req['images'];
}
I'm using a controller to handle my routes eg:
Route::post('/saveImage', 'Author\Project\Controllers\ProductControl#saveImage');
I've added an attachOne relation to the plugin as usual and my form has enctype="multipart/form-data"
I've had this problem before and got around it by converting images to base64 but this project will have quite a few images and I don't want to go down that route again.
Any suggestions greatly appreciated
You can send images as regular post and use regular $request->file('images') method in your Laravel controller.
You can use Javascript FormData object. For example;
<div>
<input type="file" #change="handleImages" multiple>
<button #click="uploadImages">Upload!</button>
</div>
data: () => ({
images: []
}),
methods: {
handleImages (event) {
this.images = event.target.files
},
uploadImages () {
const formData = new FormData();
for (const i of Object.keys(this.images)) {
formData.append('images', this.images[i])
}
axios.post('/saveImage', formData, {
}).then((res) => {
console.log(res)
})
}
}

Vue-Multiselect with Laravel 5.3

I'm new to Laravel and Vue and need help implementing Vue-Multiselect.
I don't know how to pass the actual options to the select.
My vue file:
<template>
<div class="dropdown">
<multiselect
:selected.sync="selected"
:show-labels="false"
:options="options"
:placeholder="placeholder"
:searchable="false"
:allow-empty="false"
:multiple="false"
key="name"
label="name"
></multiselect>
<label v-show="showLabel" for="multiselect"><span></span>Language</label>
</div>
</template>
<script>
import { Multiselect } from 'vue-multiselect';
export default {
components: { Multiselect },
props: {
options: {},
placeholder: {
default: 'Select one'
},
showLabel: {
type: Boolean,
default: true
},
selected: ''
}
};
</script>
My blade file:
<div class="form-group">
<drop-down
:options="{{ $members->list }}"
:selected.sync="selected"
:show-label="false"
></drop-down>
</div>
In my controller method I tried a few things:
1.
public function edit($id)
{
....
$members_list = Member::orderBy('member_first_name')->pluck('member_first_name', member_id');
return view('businesses.edit', compact('members_list'));
}
I got this error:
[Vue warn]: Invalid prop: type check failed for prop "options". Expected Array, got Object. (found in component: ).
2.I tried:
$members = Member::orderBy('member_first_name')->pluck('member_first_name', member_id');
$members_list = $members->all();
return view('businesses.edit', compact('members_list'));
I got this error:
htmlspecialchars() expects parameter 1 to be string, array given (View: C:\wamp\www\ccf.local\resources\views\businesses\edit.blade.php)
3.
$members = DB::table('members')
->orderBy('member_first_name', 'asc')
->get();
$members_list = array();
foreach($members as $mem) {
$members_list[$mem->member_id] = $mem->member_first_name;
}
I got this error: htmlspecialchars() expects parameter 1 to be string, array given (View: C:\wamp\www\ccf.local\resources\views\businesses\edit.blade.php)
So I need help with 2 things:
How to send the $members_list as the options
How can I combine the member_first_name and member_last_name fields so I can get options like this:
option value="member_id"
option text = member_first_name member_last_name
Thank you
When using prop binding inside of laravel {{ }} tries to output an escaped form of the variable.
what you need is a javascript array. if $members_list returns a collection, which seems to be indicated by your other code, try
<drop-down
:options="{{ $members_list->toJson() }}"
:selected.sync="selected"
:show-label="false"
></drop-down>
as for your controller this will help
$members = DB::table('members')
->orderBy('member_first_name', 'asc')
->get();
$members_list = $members->map(
function($member) {
return [
"value" => $member->member_id,
"label" => $member->member_first_name. " ". $member->member_last_name
];
}
);
Laravel Collections have a good selection of function that help to manipulate data will map your members array to the structure of { value: "", label: "" } when you convert to Json.
Lastly don't forget to set up your prop bindings in vue.
props: {
options: {
type: Array,
default: function() {
return [];
}
},...
}
That should get you going.

how to appear the image in ember with handlebars

Hello I want to appear the image from code i wrote below but i cant. Any ideas?
I googled and i found that i must use a helper function.
(template)
showallapps.hbs
{{#if getappsexist}}
{{#each app in getapp}}
{{#each app.app_files}}
{{#link-to "dashboard" app}}
<img {{bind-attr src=get_url}} class="img-responsive">
{{/link-to}}
{{/each}}
{{#link-to "dashboard" app}}
{{app.app_name}}
{{/link-to}}
(controller)
showallapps.js
import Ember from 'ember';
export default Ember.ObjectController.extend({
apps:[],
getappsexist: function () {
var appsexist = false;
if (this.store.all('userapp').content.length > 0) {
appsexist = true;
}
return appsexist;
}.property(),
getapp: function () {
this.apps = this.store.all('userapp');
return this.apps;
}.property(),
get_url: function (){
var url = 'http://' + JSON.parse(this.apps.content[2]._data.app_files).url;
return url;
}.property()
});
I have this json.
{
"userapp": [
{
},
{
"app_files": "{"url":"static.xxx.xxx/data/application/3911efd9-413a-11e1-b5e9-fbed80c8f6ba/eleutheris_epilogis.jpg","mime":"image/jpeg","name":"eleutheris epilogis.jpg"}"
}
]
}
I get these errors:
Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed {"url":"static.xxx.xxx/data/application/3911efd9-413a-11e1-b5e9-fbed80c8f6ba/eleutheris_epilogis.jpg","mime":"image/jpeg","name":"eleutheris epilogis.jpg"}
You need to form the image url as a property of some type in your controller (as you did with the getUrl computed property). Then you can bind to that by doing something like this:
<img {{bind-attr src=getUrl}} class="img-responsive" />

Resources