Created
December 26, 2017 14:53
-
-
Save paulund/ae573dc2122d6a88297496bce6da2b8b to your computer and use it in GitHub Desktop.
Creating a Laravel, VueJS, Algolia real time search results box.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Models; | |
use Laravel\Scout\Searchable; | |
/** | |
* Post model | |
*/ | |
class Post extends Model | |
{ | |
use Searchable; | |
/** | |
* Get the indexable data array for the model. | |
* | |
* @return array | |
*/ | |
public function toSearchableArray() | |
{ | |
return [ | |
'title' => $this->title, | |
'slug' => $this->slug, | |
'tags' => $this->tags()->pluck('title'), | |
'excerpt' => $this->excerpt | |
]; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<section class="search-results" v-show="results.length > 0"> | |
<div v-for="result in results" class="search-result"> | |
<a :href="'/' + result.slug">{{ result.title }}</a> | |
</div> | |
</section> | |
</template> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script> | |
import axios from 'axios' | |
export default { | |
props: ['query'], | |
data() { | |
return { | |
results: [] | |
}; | |
}, | |
watch: { | |
query () { | |
this.getSearchResults(); | |
} | |
}, | |
methods: { | |
getSearchResults () { | |
if(this.query === '' && this.query.length < 3) { | |
this.results = [] | |
return false | |
} | |
axios.get( '/search?q=' + this.query ) | |
.then(response => { | |
this.results = response.data.data | |
}); | |
} | |
} | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style lang="scss"> | |
.search-results { | |
position: absolute; | |
top: 0; | |
background: #FFF; | |
border: 1px solid #dae4e9; | |
width: 100%; | |
max-height: 20rem; | |
overflow-y: scroll; | |
> div { | |
margin-bottom: 0.5rem; | |
text-align: left; | |
&:hover { | |
background-color: #F1F5F8; | |
} | |
a { | |
display: block; | |
padding: 1rem; | |
} | |
} | |
} | |
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<section class="search-results" v-show="results.length > 0"> | |
<div v-for="result in results" class="search-result"> | |
<a :href="'/' + result.slug">{{ result.title }}</a> | |
</div> | |
</section> | |
</template> | |
<style lang="scss"> | |
.search-results { | |
position: absolute; | |
top: 0; | |
background: #FFF; | |
border: 1px solid #dae4e9; | |
width: 100%; | |
max-height: 20rem; | |
overflow-y: scroll; | |
> div { | |
margin-bottom: 0.5rem; | |
text-align: left; | |
&:hover { | |
background-color: #F1F5F8; | |
} | |
a { | |
display: block; | |
padding: 1rem; | |
} | |
} | |
} | |
</style> | |
<script> | |
import axios from 'axios' | |
export default { | |
props: ['query'], | |
data() { | |
return { | |
results: [] | |
}; | |
}, | |
watch: { | |
query () { | |
this.getSearchResults(); | |
} | |
}, | |
methods: { | |
getSearchResults () { | |
if(this.query === '' && this.query.length < 3) { | |
this.results = [] | |
return false | |
} | |
axios.get( '/search?q=' + this.query ) | |
.then(response => { | |
this.results = response.data.data | |
}); | |
} | |
} | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<section class="search"> | |
<search-box v-model="query" placeholder="Search for a tutorial" :show-results.sync="showResults"></search-box> | |
<div class="relative" v-show="showResults"> | |
<search-results :query="query"></search-results> | |
</div> | |
</section> | |
</template> | |
<script> | |
import SearchBox from './SearchBox' | |
import SearchResults from './Results' | |
export default { | |
data() { | |
return { | |
query: '', | |
showResults: true | |
}; | |
}, | |
components: { | |
SearchBox, | |
SearchResults | |
} | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div> | |
<input type="search" | |
:value="value" | |
:placeholder="placeholder" | |
v-on:input="updateValue($event.target.value)" | |
id="s" | |
name="s" | |
autocomplete="off"> | |
</div> | |
</template> | |
<script> | |
export default { | |
props: ['value', 'placeholder'], | |
methods: { | |
updateValue: function (value) { | |
this.$emit('input', value) | |
} | |
} | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers\Search; | |
use App\Http\Controllers\Controller; | |
use App\Models\Post; | |
use Illuminate\Http\Request; | |
/** | |
* Class SearchController | |
* @package App\Http\Controllers\Search | |
*/ | |
class SearchController extends Controller | |
{ | |
public function search(Request $request) | |
{ | |
$this->validate($request, [ | |
'q' => 'required' | |
]); | |
$posts = Post::search( $request->get('q') )->raw(); | |
if(empty($posts['hits'])) { | |
$posts['hits'] = []; | |
} | |
return response()->json(['data' => $posts['hits']]); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<section> | |
<ais-index app-id="{{ config('scout.algolia.id') }}" | |
api-key="{{ config('scout.algolia.search') }}" | |
index-name="posts_index"> | |
<div class="relative"> | |
<ais-input placeholder="Search for tutorials..."></ais-input> | |
<ais-results> | |
<template scope="{ result }"> | |
<div> | |
<h4><a :href="result.slug">@{{ result.title }}</a></h4> | |
<p><a :href="result.slug">@{{ result.excerpt }}</a></p> | |
</div> | |
</template> | |
<ais-powered-by slot="footer" /> | |
</ais-results> | |
</div> | |
</ais-index> | |
</section> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is this thing going right ?