Last active
March 14, 2019 23:25
-
-
Save ais-one/723527481566645ab33b36a933632558 to your computer and use it in GitHub Desktop.
vue-crud-x - Book.vue
This file contains 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 id="not-needed"> | |
<v-layout row wrap> | |
<v-flex xs12> | |
<vue-crud-x ref="book-table" storeName="book-table" :parentId="null" v-bind="bookDefs" @form-open="openBookForm"> | |
<template slot="filter" slot-scope="{ filterData, parentId, storeName }"> | |
<h1>Custom {{ storeName }} Filter Slot</h1> | |
<div v-for="(filter, index) in filterData" :key="index"> | |
<component :is="filter.type" v-model="filter.value" v-bind="filter.attrs"></component> | |
</div> | |
</template> | |
<!-- <template slot="table" slot-scope="{ records, totalRecs, pagination }"> | |
<div v-for="record in records" :key="record.id"><p>{{ record.id }} {{ record.name }} <v-btn @click="$refs['book-table'].crudFormOpen(record.id)">Open</v-btn></p></div> | |
<div>{{ totalRecs }} {{ pagination }}</div> | |
</template> --> | |
<template slot="form" slot-scope="{ record, parentId, storeName }"> | |
<div> | |
<h1>Custom {{ storeName }} Form Slot - Has Parent: {{ !!parentId }}</h1> | |
<v-card-text> | |
<v-text-field label="Name" v-model="record.name"></v-text-field> | |
<v-select label="Category" v-model="record.categoryId" :items="categories" required item-text="name" item-value="id"></v-select> | |
<v-autocomplete multiple v-model="authorIds" :items="items" :loading="isLoading" :search-input.sync="search" | |
chips clearable hide-selected item-text="name" item-value="id" label="Search for a author... (Maximum 2)" | |
> | |
<template slot="no-data"> | |
<v-list-tile> | |
<v-list-tile-title>No author yet...</v-list-tile-title> | |
</v-list-tile> | |
</template> | |
<template slot="selection" slot-scope="{ item, selected }"> | |
<v-chip :selected="selected" close @input="remove(item)"> | |
<span v-text="item.name"></span> | |
</v-chip> | |
</template> | |
<template slot="item" slot-scope="{ item }"> | |
<v-list-tile-content> | |
<v-list-tile-title v-text="item.name"></v-list-tile-title> | |
</v-list-tile-content> | |
</template> | |
</v-autocomplete> | |
<v-btn @click.stop.prevent="gotoPages(record.id)" dark>View Book Pages</v-btn> | |
</v-card-text> | |
</div> | |
</template> | |
</vue-crud-x> | |
</v-flex> | |
</v-layout> | |
</div> | |
</template> | |
<script> | |
import { from } from 'rxjs' | |
import { pluck, filter, debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators' // map | |
import { http } from '@/axios' | |
import VueCrudX from '@/VueCrudX' | |
export default { | |
subscriptions () { | |
return { | |
// clean autocomplete using rxJS | |
items: this.$watchAsObservable('search').pipe( | |
pluck('newValue'), filter(text => text ? text.length > 2 : false), | |
debounceTime(500), distinctUntilChanged(), switchMap(this.fetchTerm) | |
) | |
} | |
}, | |
name: 'book', | |
components: { VueCrudX }, | |
data () { | |
return { | |
// for autocomplete | |
isLoading: false, authorIds: [], search: '', | |
// list of categories - can be moved to database in future | |
categories: [ { id: 1, name: 'cat1' }, { id: 2, name: 'cat2' } ], | |
// props to be passed into vue-crud-x component | |
bookDefs: { | |
crudTable: { | |
confirmCreate: true, confirmUpdate: true, confirmDelete: true, | |
headers: [ | |
{ text: 'Book Name', value: 'name', class: 'pa-1' }, | |
{ text: 'Category', value: 'categoryName', class: 'pa-1' } | |
], | |
formatters: (value, _type) => value, // format table cell data | |
doPage: true // do pagination? | |
}, | |
crudFilter: { | |
FilterVue: null, | |
filterData: { | |
name: { // search filter by Book table property called 'name' | |
type: 'v-text-field', value: '', attrs: { label: 'Book Name' } | |
} | |
} | |
}, | |
crudForm: { | |
FormVue: () => {}, | |
formAutoData: null, | |
defaultRec: () => ({ | |
id: '', name: '', categoryId: '', categoryName: '', authorIds: [], authors: [] | |
}) | |
}, | |
crudOps: { // CRUD | |
export: async (payload) => { }, | |
find: async (payload) => { | |
let records = [] | |
const { pagination, filterData } = payload // pagination: { sortBy, descending } | |
const { page, rowsPerPage } = pagination | |
let params = { page: page > 0 ? page - 1 : 0, limit: rowsPerPage } // set query params | |
params.name = filterData.name.value | |
try { | |
const { data: { results, total } } = await http.get('/api/books', { params }) | |
results.forEach(row => { records.push(row) }) | |
pagination.totalItems = total | |
} catch (e) { } | |
return { records, pagination } | |
}, | |
findOne: async (payload) => { | |
const { id } = payload | |
try { | |
const { data } = await http.get(`/api/books/${id}`) | |
return data | |
} catch (e) { } | |
return { } | |
}, | |
create: async (payload) => { | |
try { | |
let { record: { id, ...noIdData } } = payload | |
const rv = await http.post('/api/authors', noIdData) | |
} catch (e) { return 500 } | |
return 201 | |
}, | |
update: async (payload) => { | |
try { | |
let { record: { id, name, categoryId, authorIds } } = payload // authorIds | |
const rv = await http.patch(`/api/books/${id}`, { name, categoryId, authorIds }) | |
} catch (e) { return 500 } | |
return 200 | |
}, | |
delete: null // not implemented | |
} | |
} | |
} | |
}, | |
watch: { | |
authorIds (val) { | |
if (val.length > 2) val.pop() | |
if (this.$refs['book-table']) this.$refs['book-table'].record.authorIds = val | |
} | |
}, | |
methods: { | |
gotoPages (id) { // go to pages table for selected book | |
this.$router.push({ path: `/books/${id}/pages` }) | |
}, | |
remove (item) { | |
const index = this.authorIds.indexOf(item.id) | |
if (index >= 0) this.authorIds.splice(index, 1) | |
}, | |
openBookForm (item) { | |
this.authorIds = item.authorIds | |
this.items = item.authors | |
}, | |
fetchTerm (term) { | |
return from( | |
http.get('/api/authors', { params: { page: 0, limit: 20, search: term } }).then(res => res.data.results) | |
) | |
} | |
} | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment