Created
          September 11, 2020 14:37 
        
      - 
      
 - 
        
Save Bunix/04d9bc31cdc9b2c2bf25fd0110bbdaa3 to your computer and use it in GitHub Desktop.  
Revisions
- 
        
plmrlnsnts revised this gist
Sep 10, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -29,7 +29,7 @@ Keep in mind that this implementation requires an api for fetching data, and ass ```vue <template> <data-table v-if="response" v-bind="{ columns, ...response }" @refetch="url = $event"> <!-- The value of a resource attribute will be displayed by default. --> <!-- A 'cell' slot is available if you need full control on how each cell should look like --> <template v-slot:cell="{ resource, column }">  - 
        
plmrlnsnts revised this gist
Sep 10, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -32,7 +32,7 @@ Keep in mind that this implementation requires an api for fetching data, and ass <data-table v-if="response" v-bind="{ columns, ...response } v-on:refetch="url = $event"> <!-- The value of a resource attribute will be displayed by default. --> <!-- A 'cell' slot is available if you need full control on how each cell should look like --> <template v-slot:cell="{ resource, column }"> <div>Some fancy thing is happening here<div> </template> </data-table>  - 
        
plmrlnsnts revised this gist
Sep 10, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -29,7 +29,7 @@ Keep in mind that this implementation requires an api for fetching data, and ass ```vue <template> <data-table v-if="response" v-bind="{ columns, ...response } v-on:refetch="url = $event"> <!-- The value of a resource attribute will be displayed by default. --> <!-- A 'cell' slot is available if you need full control on how each cell should look like --> <template v-slot:cell="{ resource, column }>  - 
        
plmrlnsnts revised this gist
Sep 10, 2020 . 1 changed file with 10 additions and 5 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,9 @@ Keep in mind that this implementation requires an api for fetching data, and ass ```json { "perPageOptions": [ 15, 50, 100 ], "actions": [ "Delete all", "Publish All", "Unpublish All" ], @@ -27,10 +29,13 @@ Keep in mind that this implementation requires an api for fetching data, and ass ```vue <template> <data-table v-if="response" v-bind="{ columns, ...response } v-on:refetch="url = $event"> <!-- The value of a resource attribute will be displayed by default. --> <!-- A 'cell' slot is available if you need full control on how each cell should look like --> <template v-slot:cell="{ resource, column }> <div>Some fancy thing is happening here<div> </template> </data-table> </template> <script>  - 
        
plmrlnsnts revised this gist
Sep 10, 2020 . 1 changed file with 4 additions and 5 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -13,7 +13,7 @@ Keep in mind that this implementation requires an api for fetching data, and ass "sortDirection": "asc" }, "resources": { "data": [], "from": 1, "to": 15, "total": 100, @@ -27,11 +27,10 @@ Keep in mind that this implementation requires an api for fetching data, and ass ```vue <template> <data-table v-if="response" v-bind="{ columns, ...response } @refetch="url = $event" /> </template> <script>  - 
        
plmrlnsnts revised this gist
Sep 10, 2020 . 1 changed file with 7 additions and 5 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ Keep in mind that this implementation requires an api for fetching data, and assumes the following response schema: ```json { "perPageOptions": [15, 50, 100], "actions": [ @@ -27,7 +27,11 @@ Keep in mind that this implementation requires an api for fetching data, and ass ```vue <template> <DataTable v-if="response" v-bind="{ columns, ...response } @refetch="url = $event" /> </template> <script> @@ -62,8 +66,6 @@ export default { ### Component ```vue <template> <div> <div> @@ -216,7 +218,7 @@ export default { if (! value) return if (window.confirm(`${value} selected items?`)) { this.$emit('click:action', value) } }, }  - 
        
plmrlnsnts created this gist
Sep 10, 2020 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,225 @@ Keep in mind that this implementation requires an api for fetching data, and assumes the following response schema: ``` { "perPageOptions": [15, 50, 100], "actions": [ "Delete all", "Publish All", "Unpublish All" ], "request": { "search": null, "perPage": 15, "sortAttribute": "title", "sortDirection": "asc" }, "resources": { "data": [...], "from": 1, "to": 15, "total": 100, "next_page_url": "foo?page=2", "prev_page_url": null, } } ``` ### Usage ```vue <template> <DataTable v-if="response" v-bind="{ columns, ...response } /> </template> <script> import axios from 'axios' export default { data: vm => ({ url: 'http:://link-to-your-api.json', response: null, columns: [ { name: 'Title', attribute: 'title', sortable: 'title' }, { name: 'Author', attribute: 'author', sortable: 'author' }, { name: 'Price', attribute: 'price', sortable: 'price' }, { name: 'Status', attribute: 'status' }, ], }), watch: { url: { immediate: true, handler: function () { axios.get(this.url).then({ data } => { this.response = { ...data } }) } } } } </script> ``` ### Component ```vue // DataTable.vue <template> <div> <div> <!-- Header --> <div> <form @submit.prevent> <input type="text" :value="query.search" @input="query.search = $event.target.value" /> </form> <form @submit.prevent v-if="selectedResources.length"> <select v-model="selectedAction"> <option :value="null">{{ selectedResources.length }} selected</option> <option v-for="action in actions" :key="`actions-${action}`">{{ action }}</option> </select> </form> </div> <!-- Table --> <table> <thead> <tr> <th width="1%"> <input type="checkbox" :checked="isAllSelected" @click="isAllSelected ? deselectAll() : selectAll()"/> </th> <th v-for="column in columns" :key="`columns-${column.name}`"> <a href="#" v-if="column.sortable" @click.prevent="sortBy(column.sortable)"> <span>{{ column.name }}</span> <span v-if="query.sortAttribute === column.sortable"> <svg width="16" height="16" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path v-if="query.sortDirection === 'asc'" fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path> <path v-else fill-rule="evenodd" d="M14.707 12.707a1 1 0 01-1.414 0L10 9.414l-3.293 3.293a1 1 0 01-1.414-1.414l4-4a1 1 0 011.414 0l4 4a1 1 0 010 1.414z" clip-rule="evenodd"></path> </svg> </span> </a> <span v-else> {{ column.name }} </span> </th> </tr> </thead> <tbody> <tr v-for="resource in resources.data" :key="resource.id"> <td> <input type="checkbox" :value="resource.id" v-model="selectedResources" /> </td> <td v-for="column in columns" :key="`cell-${resource.id}-${column.name}`"> <slot name="cell" v-bind="{ column, resource }"> {{ resource[column.attribute] }} </slot> </td> </tr> </tbody> </table> <!-- Footer --> <div> <div> <span>Showing:</span> <form @submit.prevent> <select v-model="query.perPage"> <option v-for="perPageOption in perPageOptions" :key="`per-page-options-${perPageOption}`" :value="perPageOption"> {{ perPageOption }} </option> </select> </form> </div> <div> {{ `${resources.from}-${resources.to} of ${resources.total}` }} </div> <div> <button v-if="resources.prev_page_url" @click="getResources(resources.prev_page_url)"> Previous </button> <span v-else> Previous </span> <button v-if="resources.next_page_url" @click="getResources(resources.next_page_url)"> Next </button> <span v-else> Next </span> </div> </div> </div> </div> </template> <script> import { pickBy, debounce } from 'lodash' export default { props: { columns: Array, perPageOptions: Array, request: Object, resources: Object, }, data: vm => ({ query: vm.request, selectedAction: null, selectedResources: [], }), computed: { isAllSelected () { return this.resources.data.length === this.resources.data .filter(resource => this.isSelected(resource)) .length }, }, methods: { isSelected (resource) { return this.selectedResources.includes(resource.id) }, selectAll () { this.resources.data .filter(resource => ! this.isSelected(resource)) .forEach(resource => this.selectedResources.push(resource.id)) }, deselectAll () { this.selectedResources.splice(0, this.selectedResources.length) }, sortBy (sortAttribute) { if (this.query.sortAttribute !== sortAttribute) { this.query.sortAttribute = sortAttribute } else { this.query.sortDirection = this.query.sortDirection === 'asc' ? 'desc' : 'asc' } }, getResources (url) { this.$emit('refetch', url) } }, watch: { query: { deep: true, handler: debounce(function (value) { let url = window.location.href.split('?')[0] let params = new URLSearchParams(pickBy(value)).toString() this.getResources(`${url}?${params}`) }, 300) }, selectedAction: function (value) { if (! value) return if (window.confirm(`${value} selected items?`)) { this.$emit('action', value) } }, } } </script> ```