I am beginner web developer. I make my first crud in Laravel 8 and Vue. I use this component t in my project: https://www.npmjs.com/package/vuejs-datatable
I have this code:
DataTable.vue:
<template> <div> <div class="row mb-3"> <div class="col-3"> <div class="input-group"> <input v-model="search" class="form-control" placeholder="Szukaj..." type="text" > <div class="input-group-append"> <button class="btn btn-primary" type="button" @click.prevent="handleSearch"> <font-awesome-icon icon="fas fa-search" /> </button> </div> </div> </div> <div class="col-2"> <div class="input-group"> <label for="pageOption" class="mt-2 mr-2">Na stronie</label> <select class="form-control" v-model="perPage" @change="handlePerPage" id="pageOption"> <option v-for="page in pageOptions" :key="page" :value="page">{{ page }}</option> </select> </div> </div> </div> <table class="table table-hover"> <thead> <tr> <th class="table-head">#</th> <th v-for="column in columns" :key="column" @click="sortByColumn(column)" class="table-head"> {{ column | columnHead }} <span v-if="column === sortedColumn"> <font-awesome-icon v-if="order === 'asc' " icon="fas fa-angle-up" /> <font-awesome-icon v-else icon="fas fa-angle-down" /> </span> </th> </tr> </thead> <tbody> <tr class="" v-if="tableData.length === 0"> <td class="lead text-center" :colspan="columns.length + 1">Brak danych do wyświetlenia.</td> </tr> <tr v-for="(data, key1) in tableData" :key="data.id" class="m-datatable__row" v-else> <td>{{ serialNumber(key1) }}</td> <td v-for="(value, key) in data">{{ value }}</td> </tr> </tbody> </table> </div> </template> <script type="text/ecmascript-6"> import axios from 'axios'; import Vue from 'vue'; import 'vuejs-datatable/dist/themes/bootstrap-4.esm'; import { VuejsDatatableFactory, IDataFnParams, IDisplayHandlerParam, ITableContentParam, TColumnsDefinition, VueDatatable } from 'vuejs-datatable'; Vue.use(VuejsDatatableFactory, VueDatatable); export default { props: { fetchUrl: {type: String, required: true}, columns: {type: Array, required: true}, }, data() { return { tableData: [], url: '', pagination: { meta: {to: 1, from: 1} }, offset: 4, currentPage: 1, perPage: 1, sortedColumn: this.columns[0], order: 'asc', search: null, pageOptions: [1, 10, 20, 50], } }, watch: { fetchUrl: { handler: function (fetchUrl) { this.url = fetchUrl }, immediate: true } }, created() { return this.fetchData() }, computed: { /** * Get the pages number array for displaying in the pagination. * */ pagesNumber() { if (!this.pagination.meta.to) { return [] } let from = this.pagination.meta.current_page - this.offset if (from < 1) { from = 1 } let to = from + (this.offset * 2) if (to >= this.pagination.meta.last_page) { to = this.pagination.meta.last_page } let pagesArray = [] for (let page = from; page <= to; page++) { pagesArray.push(page) } return pagesArray }, /** * Get the total data displayed in the current page. * */ totalData() { return (this.pagination.meta.to - this.pagination.meta.from) + 1 } }, methods: { fetchData() { let dataFetchUrl = `${this.url}&page=${this.currentPage}&column=${this.sortedColumn}&order=${this.order}&per_page=${this.perPage}` axios.get(dataFetchUrl) .then(({data}) => { this.pagination = data this.tableData = data.data }).catch(error => this.tableData = []) }, /** * Get the serial number. * @param key * */ serialNumber(key) { return (this.currentPage - 1) * this.perPage + 1 + key }, /** * Change the page. * @param pageNumber */ changePage(pageNumber) { this.currentPage = pageNumber this.fetchData() }, /** * Sort the data by column. * */ sortByColumn(column) { if (column === this.sortedColumn) { this.order = (this.order === 'asc') ? 'desc' : 'asc' } else { this.sortedColumn = column this.order = 'asc' } this.fetchData() }, handleSearch() { this.fetchData() }, handlePerPage($event) { this.perPage = $event.target.value; this.fetchData() } }, filters: { columnHead(value) { return value.split('_').join(' ').toUpperCase() } }, translate: { nextButton: 'Dalej', previousButton: 'Wstecz', placeholderSearch: 'Szukaj...', }, name: 'DataTable' } </script> <style scoped> </style>
Notes.vue:
<template> <CRow> <CCol col="12"> <transition name="slide"> <CCard> <CCardBody> <h4> Menus </h4> <CButton color="success" @click="createNote()" class="mb-3 my-5">Add Menu <font-awesome-icon icon="fas fa-plus" /> </CButton> <div class="flex-center position-ref full-height"> <data-table :fetch-url="datatTableUrl" :columns="['name', 'email', 'id' , 'created_at']" :headers="['nazwa', 'adres email', 'ID' , 'utworzono']" ></data-table> </div> </CCardBody> </CCard> </transition> </CCol> </CRow> </template> <script> import Vue from 'vue'; export default { data() { return { datatTableUrl: '', } }, created: function () { this.datatTableUrl = Vue.prototype.$apiAdress + '/api/users/dataTable' + '?token=' + localStorage.getItem("api_token"); }, methods: { noteLink(id) { return `notes/${id.toString()}` }, editLink(id) { return `notes/${id.toString()}/edit` }, showNote(id) { const noteLink = this.noteLink(id); this.$router.push({path: noteLink}); }, editNote(id) { const editLink = this.editLink(id); this.$router.push({path: editLink}); }, deleteNote(id) { let self = this; let noteId = id; axios.post(this.$apiAdress + '/api/notes/' + id + '?token=' + localStorage.getItem("api_token"), { _method: 'DELETE' }) .then(function (response) { self.message = 'Successfully deleted note.'; self.showAlert(); self.getNotes(); }).catch(function (error) { console.log(error); self.$router.push({path: '/login'}); }); }, createNote() { this.$router.push({path: 'notes/create'}); }, } } </script>
This code work fine.
I have 2 problems:
I would like the column headers in the table to be taken from: headers – currently these are the column names from the database (ie: columns).
I would like to add a link to edit and delete a record. I have created methods: editLink (), deleteNote (). How can I add them to my table? I would like them to be visible next to the “name” column
How can I make it?
Please help me 🙂
Advertisement
Answer
For the problem #1. I would do it this way. Merge the columns and the headers as one Object, ex: where the key will be the column name (Important: don’t forget to register the headers prop).
<data-table :fetch-url="datatTableUrl" :headers="{'name': 'nazwa','email': 'adres email','id': 'ID' , 'created_at': 'utworzono'}" ></data-table>
In the DataTable:
<th v-for="(column, label) in headers" :key="column" @click="sortByColumn(column)" class="table-head"> {{ label | columnHead }} <span v-if="column === sortedColumn"> <font-awesome-icon v-if="order === 'asc' " icon="fas fa-angle-up" /> <font-awesome-icon v-else icon="fas fa-angle-down" /> </span> </th>
For the Second problem #2 (Not very clear), Better to move these functions to the DataTable and add the actions as a new column, short example:
<td><button @click="editLink(key1)">Edit link or some fa fa icon</button></td>
Add as prop in the DataTable:
props: { fetchUrl: {type: String, required: true}, columns: {type: Array, required: true}, headers: {type: Object, required: true} //<-- This },