Skip to content

Instantly share code, notes, and snippets.

@benyarb
Created February 25, 2018 03:29
Show Gist options
  • Save benyarb/dced7ee996612ba745ac5ed13148915c to your computer and use it in GitHub Desktop.
Save benyarb/dced7ee996612ba745ac5ed13148915c to your computer and use it in GitHub Desktop.
API Resource Search
Vue.component('resource-search', {
props: {
selected: [],
selectedData: [],
resourceName: '',
searchTarget: '', // which property on the resource to search
haystackLimit: [],
},
data() {
return {
resourceUri: `/api/${this.resourceName}/`,
resource: [],
search: '',
isLoading: true,
isSearching: false,
}
},
computed: {
haystack() {
if (this.haystackLimit && this.haystackLimit.length > 0) {
return _.filter(this.resource, (item) => {
return _.contains(this.haystackLimit, item.id);
});
}
return this.resource;
},
},
watch: {
selected() {
this.setSelectedData();
},
haystackLimit() {
this.selected = _.intersection(this.selected, this.haystackLimit);
},
},
template: `
<div class="resource-search" id="resource-search-{{ _uid }}">
<input type="search" v-model="search" id="resource-search-{{ _uid }}-input" class="form-control" placeholder="Search" />
<span v-show="isSearching" class="resource-search-reset" @click="reset"><i class="fa fa-times" aria-hidden="true"></i></span>
<div v-show="isSearching" class="resource-search-results" id="resource-search-{{ _uid }}-results">
<label v-for="item in haystack | filterBy search in searchTarget" for="{{ resourceName }}-{{ item.id }}" class="resource-search-result control-label {{ isSelected(item.id) ? 'selected' : '' }}">
<input type="checkbox" value="{{ item.id }}" number v-model="selected" id="{{ resourceName }}-{{ item.id }}" />
<i class="fa {{ isSelected(item.id) ? 'fa-minus' : 'fa-plus' }}" aria-hidden="true"></i>
<span v-text="item[searchTarget]"></span>
</label>
<div v-show="isLoading" class="resource-search-loading">Loading...</div>
<div class="resource-search-no-results">No results found.</div>
</div>
<div v-show="selected.length > 0 && !isSearching" class="resource-search-selections">
<template v-for="item in haystack">
<label v-if="isSelected(item.id)" for="{{ resourceName }}-{{ item.id }}" class="resource-search-result control-label {{ isSelected(item.id) ? 'selected' : '' }}">
<input type="checkbox" value="{{ item.id }}" number v-model="selected" id="{{ resourceName }}-{{ item.id }}" />
<i class="fa {{ isSelected(item.id) ? 'fa-minus' : 'fa-plus' }}" aria-hidden="true"></i>
<span v-text="item[searchTarget]"></span>
</label>
</template>
</div>
</div>`,
created() {
this.getResource();
},
ready() {
$(`#resource-search-${ this._uid }-input`).focus(() => {
this.isSearching = true;
});
// click outside closes search results
$(document).click(event => {
if(!$(event.target).closest(`#resource-search-${this._uid}`).length) {
if($(`#resource-search-${this._uid} .resource-search-results`).is(":visible")) {
this.isSearching = false;
}
}
});
},
methods: {
getResource() {
this.$http.get(this.resourceUri)
.then(response => {
this.resource = response.data;
this.isLoading = false;
});
},
isSelected(id) {
return _.contains(this.selected, id);
},
setSelectedData() {
if (this.selected) {
this.selectedData = _.filter(this.haystack, (item) => {
return _.contains(this.selected, item.id);
});
} else {
this.selectedData = [];
}
},
reset() {
this.search = '';
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment