Skip to content

Instantly share code, notes, and snippets.

@kornatzky
Created January 5, 2018 13:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kornatzky/18e1073d1972a46cbfae2fbf61c7969e to your computer and use it in GitHub Desktop.
Save kornatzky/18e1073d1972a46cbfae2fbf61c7969e to your computer and use it in GitHub Desktop.
Vue.js Typeahead
/* eslint no-console: ["error", { allow: ["log"] }] */
<template>
<div class="typeahead">
<input
v-model="query"
@focus="reset"
type="text"
class="search-input"
v-bind:placeholder="field.placeholder"
>
<ul class="results" v-if="!selected">
<li v-for="item in items" :key="item.id" v-on:click="selectedItem(item)">
<span>
<strong>{{ item.value }}</strong>
</span>
</li>
</ul>
</div>
</template>
<script lang="js">
import _ from 'lodash';
import backand from `@/backend`;
export default {
name: 'typeahead',
props: ['startAt', 'field'],
data() {
return {
items: [],
query: '',
selected: false,
};
},
mounted() {
},
computed: {
isEmpty() {
if (!this.query) {
return false;
}
return this.items.length < 1;
},
},
methods: {
fetchItems() {
const q = this.query.trim();
backand.getAutocomplete(q, this.field.key)
.then((results) => {
this.items = this.extractItems(results, this.field);
});
},
extractItems(results, field) {
return _.concat([{ id: null, value: 'none selected' }], _.map(results, r => ({ id: r.id, value: r[this.field.autocomplete] })));
},
reset() {
this.items = [];
this.selected = false;
},
selectedItem(item) {
this.selected = true;
if (item.id) {
this.query = item.value;
this.$emit('selected', { field: this.field.key, value: item.id });
} else {
this.query = '';
}
},
},
watch: {
query(to, from) {
if (this.query.trim().length >= this.startAt) {
this.fetchItems();
}
},
},
};
</script>
<style scoped lang="scss">
$height: 18.95vh;
.typeahead {
flex: 2;
height: $ * 0.2;
.search-input {
position: relative;
width: 100%;
height: $height * 0.2;
font-family: AvenirNext;
font-size: 14px;
font-weight: bold;
text-align: left;
color: #a7aaac;
margin: 0;
padding: 0;
font-size: 1em;
outline: 0;
position: relative;
color: #2e3d42;
}
.search-input::placeholder {
font-family: AvenirNext;
font-size: 14px;
font-weight: bold;
text-align: left;
color: #2e3d42;
padding-left: 5%;
}
.search-input:hover {
border: 1px solid #0097ce;
}
.search-input:focus {
border: 1px solid #0097ce;
}
.search-input:active {
border: 1px solid #0097ce;
}
.results {
margin: 0;
padding: 0;
text-align: left;
position: relative;
opacity: 1;
z-index: 1000;
li {
font-family: AvenirNext;
font-size: 14px;
font-weight: bold;
text-align: left;
color: #2e3d42;
background-color: #fdfefe;
margin: 0;
padding: 1em;
list-style: none;
width: 100%;
}
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment