Vue Good Table Component, insert html in filter select options - vuejs2

I am a web-designer, i am working in laravel 5.8 with vue js 2, this is a work for my company.
I have a vue good table component and i want in the flags(languages) column a filter with a drop-down options.
The options(list of languages(example: pt,fr and gb)) are coming from database by a axios request.
Don't want the languages to appear in the filter options with name of the languages but with "span" for a flags icon
(Example: "<span :class="'flag-icon flag-icon-gb
flag-icon-squared'"></span>" ).
This examples works just fine with a row scope and get the flags but in the filter I can get it to translate to html just gives the line as plain text.
I have already tried with "html: true," and "htmlContent: <span></span>"
The scop for the row flag works just fine
vue component scop
<template slot="table-row" slot-scope="row">
<span class="text-center" v-if="row.column.field == 'language.name'">
<span :class="'flag-icon flag-icon-' + row.formattedRow[row.column.field] + ' flag-icon-squared'"></span>
</span>
<span v-else>
{{ row.formattedRow[row.column.field] }}
</span>
</template>
The table data
data() {
return {
columns: [
{
label: 'Name',
field: 'user.name',
filterOptions: {
enabled: true
}
},
{
label: 'Country',
field: 'language.name',
html: true,
filterOptions: {
enabled: true,
filterDropdownItems: []
}
},
{
label: 'Status',
field: 'status.name',
filterOptions: {
enabled: true,
filterDropdownItems: []
}
},
{
label: 'Property',
field: 'property.title',
filterOptions: {
enabled: true,
filterDropdownItems: []
}
},
{
label: 'Last Reply',
field: 'updated_at',
type: 'date',
dateInputFormat: 'YYYY-MM-DD hh:mm:ss',
dateOutputFormat: 'Do MMM YYYY',
filterOptions: {
enabled: true
}
},
{
label: 'Create Date',
field: 'created_at',
type: 'date',
dateInputFormat: 'YYYY-MM-DD hh:mm:ss',
dateOutputFormat: 'Do MMM YYYY',
filterOptions: {
enabled: true
}
},
],
rows: [],
totalRecords: 0,
serverParams: {
columnFilters: {},
sort: {
field: '',
type: '',
},
page: 1,
perPage: 10
}
}
},
The axios request where i get the language list and try to put the span in the filter options
vue
getLanguages() {
let url = '/manage/data/request-language';
axios.get(url)
.then(({status, data}) => {
if (status === 200) {
data.records.forEach(item => {
let newData = {value: item.id, html: true, text: "<span :class='flag-icon flag-icon-" + item.name + " flag-icon-squared'></span>"};
this.columns[1].filterOptions.filterDropdownItems.push(newData);
});
}
}).catch(error => Alert.handleRequestError(error));
},
I expect to appear a flag list and not a span list of the flags.
Is it possible to override that specific filter or to force it html instead of plain text?

Related

Cannot read properties of undefined on formatter, but data is showing fine

I have a bootstrap table that shows a list of appliances. I am importing my data with Axios and for this specific table I am outputting data from two database tables, so I have one object which is called applianceReferences which stores another object called activeAppliances.
Not sure if it is relevant for this question, but just so you know.
Before talking about the problem, let me just post the whole code and below I will talk about the section that is giving me issues.
<template>
<b-container class="my-2">
<b-card v-if="showTable" class="ml-4 mr-4">
<b-table
search-placeholder="search"
:filter-included-fields="fields.map(f => f.key)"
include-filter
:items="applianceReferences"
:fields="fields"
/>
</b-card>
</b-container>
</template>
<script>
import {applianceService} from "#/services/appliance";
import CommonCollapsible from "#/components/common/CommonCollapsible";
import moment from 'moment';
export default {
components: { CommonCollapsible, CommonTable },
props: {
ownerId: String,
ownerType: String,
showDocuments: Boolean,
goToAppliances: "",
importAppliances: ""
},
data() {
return {
applianceReferences: [],
showTable: true
}
},
computed: {
fields() {
return [
{
key: 'referenceName',
label: this.$t('referenceName'),
sortable: true
},
{
key: 'activeAppliance.type',
label: this.$t('type'),
sortable: true,
},
{
key: 'activeAppliance.brandName',
label: this.$t('brand'),
sortable: true
},
{
key: 'activeAppliance.purchaseDate',
label: this.$t('purchaseDate'),
sortable: true,
template: {type: 'date', format: 'L'}
},
{
key: 'activeAppliance.warrantyDuration',
label: this.$t('warrantyDuration'),
sortable: true,
formatter: (warrantyDuration, applianceId, appliance) =>
this.$n(warrantyDuration) + ' ' +
this.$t(appliance.activeAppliance.warrantyDurationType ?
`model.appliance.warrantyDurationTypes.${appliance.activeAppliance.warrantyDurationType}` :
''
).toLocaleLowerCase(this.$i18n.locale),
sortByFormatted: (warrantyDuration, applianceId, appliance) =>
appliance.activeAppliance.warrantyDurationType === 'YEARS' ? warrantyDuration * 12 : warrantyDuration
},
{
key: 'activeAppliance.purchaseAmount',
label: this.$t('amount'),
sortable: true,
template: {
type: 'number', format: {minimumFractionDigits: '2', maximumFractionDigits: '2'},
foot: sum
}
},
{
key: 'actions',
template: {
type: 'actions',
head: [
{
text: 'overviewOfAppliances',
icon: 'fas fa-fw fa-arrow-right',
action: this.createAppliance
},
{
icon: 'fas fa-fw fa-file-excel',
action: this.importAppliance,
tooltip: this.$t('importAppliances'),
}
],
cell: [
{
icon: 'fa-trash',
variant: 'outline-danger',
action: this.remove
},
]
}
}
]
},
},
methods: {
load() {
Object.assign(this.$data, this.$options.data.apply(this));
this.applianceReferences = null;
applianceService.listApplianceReferences(this.ownerId).then(({data: applianceReferences}) => {
this.applianceReferences = applianceReferences;
this.applianceReferences.forEach( reference => {
applianceService.listAppliances(reference.id).then(result => {
this.$set(reference, 'appliances', result.data);
this.$set(reference, 'activeAppliance', result.data.find(appliance => appliance.active))
this.loaded = true
})
})
}).catch(error => {
console.error(error);
})
},
createAppliance(){
this.goToAppliances()
},
importAppliance(){
this.importAppliances()
},
},
watch: {
ownerId: {
immediate: true,
handler: 'load'
}
},
}
</script>
Okay, so the error occurs in this specific property:
{
key: 'activeAppliance.warrantyDuration',
label: this.$t('warrantyDuration'),
sortable: true,
formatter: (warrantyDuration, applianceId, appliance) =>
this.$n(warrantyDuration) + ' ' +
this.$t(appliance.activeAppliance.warrantyDurationType ?
`model.appliance.warrantyDurationTypes.${appliance.activeAppliance.warrantyDurationType}` :
''
).toLocaleLowerCase(this.$i18n.locale),
sortByFormatted: (warrantyDuration, applianceId, appliance) =>
appliance.activeAppliance.warrantyDurationType === 'YEARS' ? warrantyDuration * 12 : warrantyDuration
},
What I am basically doing here is combining two values from the object: warrantyDuration and warrantyDurationType and putting them in one single row in my bootstrap table.
The problem is that this is giving me an error: Cannot read properties of undefined (reading 'warrantyDurationType'
Yet the data actually outputs normally.
So what exactly does it want me to do?
I tried wrapping a v-if around the table to make sure that the application checks if the data exist before outputting it, but this does not solve the issue.
<div v-if="applianceReferences && applianceReferences.activeAppliance">
<b-card v-if="showTable" class="ml-4 mr-4">
<common-table
search-placeholder="search"
:filter-included-fields="fields.map(f => f.key)"
include-filter
:items="applianceReferences"
:fields="fields"
/>
</b-card>
</div>
Last, just to give you a full overview, my array looks like this:
Any ideas?

Vue Good Table how to access data in Selected Row Actions

I'm trying to use the checkbox in vue-good-table to select rows, then a button in the selected row action slow to perform a function on the selected rows. How can I access the data?
https://xaksis.github.io/vue-good-table/guide/advanced/checkbox-table.html#selected-row-action-slot
This doesn't work:
<vue-good-table
#on-selected-rows-change="selectAll"
:columns="columns2"
id="shift.id"
:ref="shift.id"
:rows="orderedPlacedUsers(shift)"
:select-options="{
enabled: true,
selectOnCheckboxOnly: true,
}"
>
<div slot="selected-row-actions">
<button class="btn btn__small btn__flat" #click="lockAll(shift)">Lock All <i class="ml-2 fas fa-lock-alt"></i></button>
</div>
</div>
</vue-good-table>
Then
data() {
return {
columns2: [
{
label: '',
field: 'extras',
tdClass: 'text-center',
sortable: false,
},
{
label: 'Name',
field: 'fullName',
},
{
label: 'Signed Up',
field: 'created',
sortable: false,
},
{
label: 'Job',
field: 'requestedJob.title',
tdClass: 'text-center',
},
{
label: '',
field: 'notes',
sortable: false,
tdClass: 'text-center',
},
{
label: '',
field: 'reservations',
tdClass: 'text-center',
tdClass: 'text-center',
sortable: false,
},
{
label: '',
field: 'delete',
tdClass: 'text-center',
sortable: false,
},
]
}
}
methods: {
lockAll(shift) {
console.log(shift.id)
console.log(this.$refs[shift.id].selectedRows)
},
orderedPlacedUsers (shift) {
function compare(a, b) {
if (a.firstName < b.firstName)
return -1;
if (a.firstName > b.firstName)
return 1;
return 0;
}
return this.filteredPlacedUsers.sort(compare).filter(user => {
return user.shift == shift.id && user.day == shift.day
});
},
}
The shift is "shift in eventShifts"... here's what that looks like:
{"day":"2021-08-27","endTime":null,"payrollComplete":true,"startTime":"14:00","event":"Los Bukis","id":"dvaBm5wQXMXvVCGBSK8e","exportedCont":{"seconds":1631208172,"nanoseconds":886000000},"collapse":false,"position":{"title":null},"selectedStaff":null,"eventId":"CGHMVzcKPnNLsmRxoeVj","exportedEmp":{"seconds":1631208185,"nanoseconds":622000000},"name":"Line Cook","staff":"50"}
Thank you!
To access the vue-good-table via this.$refs you need to add :ref property into vue-good-table.
<vue-good-table
:id="shift.id"
:ref="shift.id"
>
</vue-good-table>
But there is another thing to be considered, it says here that
When used on elements/components with v-for, the registered reference
will be an Array containing DOM nodes or component instances.
In your case, probably vue-good-table is used on an element/component with v-for. So, you can access it via this.$refs[shift.id][0]. Finally, you can print the selectedRows using console.log(this.$refs[shift.id][0].selectedRows)

Display Selected values in v-select multiple

I am new in vue js. Using vue2, I have a v-select implemented on my site now, I want to select multiple values and save and show them while editing. But I can't show multiple values properly using :reduce
Here is my code:
<v-select name="allowed_extensions"
:reduce="allowed_extensions => allowed_extensions.value"
multiple
:closeOnSelect="false"
v-model="form.allowed_extensions"
:options="file_options"
v-validate="'required'" > </v-select>
In js:
data () {
return {
isDisabled: false, //Submit Button
form: {
maximum_file_size: '',
allowed_extensions: ''
},
be_errors: {},
// Options
file_options: [
{ label: 'doc', value: 'doc' },
{ label: 'docx', value: 'docx' },
{ label: 'pdf', value: 'pdf' },
{ label: 'txt', value: 'txt' },
{ label: 'gif', value: 'gif' },
{ label: 'png', value: 'png' },
{ label: 'jpg', value: 'jpg' },
{ label: 'jpeg', value: 'jpeg' }
]
}
}
IN Mysql DB, sample data saved as : ["doc","txt"]
But when I want to display them in edit, it showing wrongly in a single tag.
How can I solve this

BootstrapVue table pagination not rendering results properly

I'm using bootstrap-vue with version 2.9.0. When navigating to another page, the result does not display unless I click on to another page then the previous page will show up then immediately show the current page, which I find it really weird.
Here's a snippet:
<b-table
:items="dataTable.customerList"
:fields="dataTable.fields"
:per-page="dataTable.perPage"
:current-page="dataTable.currentPage"
:sort-by.sync="dataTable.sortBy"
:sort-desc.sync="dataTable.sortDesc"
:no-local-sorting="true"
#sort-changed="sortingChanged"
responsive
striped
hover
show-empty
empty-text="Loading..."
id="tbl-customer-list"
busy.sync="true"
>
</b-table>
<b-pagination
v-model="dataTable.currentPage"
:total-rows="dataTable.totalRows"
:per-page="dataTable.perPage"
#input="getCustomers(dataTable.currentPage)"></b-pagination>
And the JS:
export default {
page: {
title: 'Customers',
meta: [{ name: 'description', content: appConfig.description }],
},
components: {
Layout,
PageHeader,
},
methods: {
getCustomers(currentPage) {
this.busy = true;
customerList({page: currentPage}).then((response) => {
this.dataTable.customerList = response.data;
this.dataTable.totalRows = response.total;
this.dataTable.currentPage = response.current_page;
this.dataTable.perPage = response.per_page;
this.dataTable.lastPage = response.last_page;
this.busy = false;
})
},
sortingChanged(ctx) {
console.log(ctx);
this.$root.$emit('bv::table::refresh', 'tbl-customer-list')
},
},
mounted() {
this.getCustomers();
},
data() {
return {
title: 'Customers',
busy: false,
dataTable: {
customerList: [],
fields: [
{ key: 'customer_name', label: 'Full Name', sortable: true },
{ key: 'actions', sortable: false },
],
totalRows: 0,
currentPage: 1,
perPage: 0,
lastPage: 1,
sortBy: 'first_name',
sortDesc: false,
filter: null,
filterOn: [],
},
}
},
}
When I remove :current-page="dataTable.currentPage" on the b-table, it works fine but I when clicking on the row headers will always display the current page as 1. (See sortingChanged)

vue good table - 3 requests to the service

I use vue-good-table object to render table in Vue.js. I use paging and sorting serverside.
My code:
<vue-good-table v-if="authorizations"
id="AuthorizationsTable"
ref="refToAuthorizationsTable"
#on-page-change="onPageChange"
#on-sort-change="onSortChange"
#on-column-filter="onColumnFilter"
#on-per-page-change="onPerPageChange"
mode="remote"
:columns="columns"
:rows="authorizations"
:totalRows="totalRecords"
:pagination-options="{
enabled: true,
mode: 'pages',
nextLabel: 'następna',
prevLabel: 'poprzednia',
ofLabel: 'z',
pageLabel: 'strona',
rowsPerPageLabel: 'wierszy na stronie',
allLabel: 'wszystko',
dropdownAllowAll: false
}"
:sort-options="{
enabled: true,
initialSortBy: {
field: 'id',
type: 'asc'
}
}">
(...)
export default {
name: 'AuthoritiesAdministration',
components: {},
data() {
return {
totalRecords: 0,
serverParams: {
columnFilters: {},
sort: {
field: 'id',
type: 'asc'
},
page: 1,
perPage: 10
},
rows: [],
columns: [
{
label: 'ID',
field: 'id',
type: 'number',
tdClass: 'vue-good-table-col-100'
},
{
label: 'Data wystawienia',
field: 'issueDate',
formatFn: this.formatDate,
tdClass: 'vue-good-table-col-200',
},
{
label: 'Nazwa operatora',
field: 'operator',
sortable: true,
formatFn: this.formatOperatorName,
},
{
label: 'Login',
field: 'operator.login'
},
{
label: 'Spółka',
field: 'company.description',
type: 'text',
},
{
label: 'Data ważności',
field: 'endDate',
type: 'text',
formatFn: this.formatDate,
},
{
label: 'Akcje',
field: 'btn',
tdClass: 'vue-good-table-col-250',
sortable: false
}
],
}
},
(...)
methods: {
updateParams(newProps) {
this.serverParams = Object.assign({}, this.serverParams, newProps);
},
onPageChange(params) {
this.updateParams({page: params.currentPage});
this.loadAuthorizations();
},
onPerPageChange(params) {
this.updateParams({
perPage: params.currentPerPage
});
this.loadAuthorizations();
},
onSortChange(params) {
this.updateParams({
sort: {
type: params[0].type,
field: params[0].field
}
});
this.loadAuthorizations();
},
onColumnFilter(params) {
this.updateParams(params);
this.loadAuthorizations();
},
loadAuthorizations() {
getAllAuthorizationsLightWithPagination(this.$store.getters.loggedUser.token, this.serverParams).then(response => {
this.totalRecords = response.data.totalRecords;
this.rows = response.data.authorizations;
}).catch(err => {
this.$showError(err, true);
});
},
I have noticed that there are sent 3 requests to the server instead of 1: there are called methods like onPageChange, onPerPageChange and onSortChange but only the first time when my page is loaded. It is unnecessary. I have one method in "mounted" section where I load the first 10 results (sorting and paging by default). It's common, well-known problem with vue-good-table? Or maybe should I add an additional flag to not to invoke these 3 methods unnecessarily when the page is loaded?
Your onSortChange method is called at the table loading because you made a initialSortBy with specific values. To remove this calling juste remove
initialSortBy: {
field: 'id',
type: 'asc'
}
from you table configuration, but your sort will not be set, so I think this should be a legit function call.
The onPerPageChange and onPageChange are triggered by the config below
:pagination-options="{
enabled: true,
...
}
just remove the colon before pagination-options to have a config like this
pagination-options="{
enabled: true,
...
}