vuejs reactivity with variable initiated in mounted function - vue.js

I have a dynamic component building multiple select, the template :
<template>
<div>
<b-field
v-for="(key,index) in allSelects"
:key="index"
:label="key"
>
<b-select
:placeholder="key"
v-model="values[key]"
>
<option
v-for="(value,index) in optionsValues(key)"
:key="index"
:value="value"
>
{{ value }}
</option>
</b-select>
</b-field>
</div>
</template>
and the script is
<script>
export default {
name: 'Test',
data () {
return {
allSelects: ['select1', 'select2'],
values: {}
}
},
computed: {
optionsValues: function () {
return key => { return this.getData(key) }
}
},
methods: {
getData: function (key) {
if (key === 'select1') {
return ['valA', 'valB', 'valC', 'valD']
} else {
if (this.values.select1 === 'valA') {
return ['A', 'AA', 'AAA', 'AAAA', 'AAAAA']
} else if (this.values.select1 === 'valB') {
return ['B', 'BB', 'BBB', 'BBBB', 'BBBBB']
} else if (this.values.select1 === 'valC') {
return ['C', 'CC', 'CCC', 'CCCC', 'CCCCC']
} else {
return ['D', 'DD', 'DDD', 'DDDD', 'DDDDD']
}
}
}
},
mounted () {
// code
}
}
</script>
In the mounted function, if I define the code as :
mounted () {
this.values = {
select1: null,
select2: null
}
}
Everything is working juste fine, the values of select1 change the values of select2, but if I dynamically build it as following :
mounted () {
for (let val of this.allSelects) {
this.values[val] = null
}
}
it's no longer working ! I would like it to be dynamic, the content of allSelects is dynamic in my real component. What would be the best solution ?

You are using Vue 2, aren't you? To add a reactive property to an object in Vue 2 you have to set it with Vue.set() (see documentation). So this should work:
mounted () {
for (let val of this.allSelects) {
Vue.set(this.values, val, null)
}
}
Alternatively, you can initialize the object with the desired structure:
const selectIds = ['select1', 'select2']
export default {
name: 'Test',
data () {
return {
allSelects: selectIds.reduce( (s, i) => ({...s, [i]: null}), {}),
values: selectIds,
}
},

Related

How to run a specific function if the component has been called by a specific component and not by other components in Vue?

I have a component called select-diagnosis which is used by many different components.
When select-diagnosis is called by a specific component called PtdTreatment, it needs to run a specific function inside the fetchDiagnosis function, while when called by other components it will not run that specific function.
The fetchDiagnosis needs to understand that select-diagnosis component has been called by the PtdTreatment component.
How to do something like that?
This is the code from PtdTreatment component:
<el-form-item
label="diagnosis"
prop="dimission_diagnosis"
v-if="form.data_dimission">
<select-diagnosis
v-model="form.diagnosis_dimission"
:defaultValue="_.get(record, 'clean_diagnosis_dimission')"
/>
</el-form-item>
And this is the select-diagnosis component:
<template>
<el-select
v-bind="$attrs"
:value="value"
#change="onChange"
#clear="onClear"
clearable
filterable
remote
:remote-method="fetchDiagnosis"
:loading="loadingSelect"
>
<el-option
v-for="item in items"
:key="`diagnosis-${item.id}`"
:label="item.code + ' - ' + item.description"
:value="item.code"
>
</el-option>
</el-select>
</template>
<script>
export default {
name: "SelectDiagnosis",
inheritAttrs: false,
props: ["value", "defaultValue"],
data() {
return {
loadingSelect: false,
items: []
};
},
methods: {
fetchDiagnosis(query) {
const valid = query !== "" && query.length > 2;
if (!valid) return;
this.loadingSelect = true;
let params = { string: query };
axios
.get("/config/diagnosi", { params })
.then(({ data }) => {
//pseudo code
// if this component is called by **select-diagnosis** then do this
this.items = data.filter(diagnosi => {
const code = diagnosi.codice.replace(/\b0+/g, "");
if (code.length >= 4) {
return diagnosi;
}
});
// else do this
this.items = data;
})
.finally(() => (this.loadingSelect = false));
},
onChange(x) {
this.$emit("input", x);
},
onClear() {
this.$emit("input", null);
this.items = [];
}
},
watch: {
defaultValue: {
immediate: true,
handler(newVal, oldVal) {
if (newVal && oldVal === undefined) {
this.items = [newVal];
this.$emit("input", newVal.codice);
}
}
}
}
};
</script>
There are a number of ways to accomplish this, the two that come to mind immediately use props.
You could pass a filterDiagnoses boolean prop to select-diagnosis. If it's true, run the filter logic.
<select-diagnosis v-model="form.diagnosis_dimission" :defaultValue="_.get(record, 'clean_diagnosis_dimission')" :filterDiagnoses="true" />
You could invert control to the parent function and expose a filterFn callback prop - the parent function passes a function prop to the child that the child will call upon fetching the diagnoses (this feels cleaner and more extensible):
/* in the PtdTreatment component */
/* ... */
methods: {
filterDiagnosis(data) {
// filter data
},
}
/* in the PtdTreatment template */
<select-diagnosis v-model="form.diagnosis_dimission" :defaultValue="_.get(record, 'clean_diagnosis_dimission')" :filterFn="filterDiagnosis" />
/* in the select-diagnosis component */
fetchDiagnosis(query) {
const valid = query !== "" && query.length > 2;
if (!valid) return;
this.loadingSelect = true;
let params = { string: query };
axios
.get("/config/diagnosis", { params })
.then(({ data }) => {
if (this.filterFn) {
this.items = this.filterFn(data);
} else {
this.items = data;
}
})
.finally(() => (this.loadingSelect = false));
},
}
You can set a prop on the child component which specifies the 'identity' of the parent component, then test for that in the child:
<select-diagnosis
v-model="form.diagnosis_dimission"
:defaultValue="_.get(record, 'clean_diagnosis_dimission')"
parent="PtdTreatment"
/>
Then in the child (simplified example):
export default {
props: ["value", "defaultValue", "parent"],
methods: {
fetchDiagnosis(query) {
if (this.parent === "PtdTreatment") {
// Parent-specific code here
}
}
}
}

Error when attempting to disable Navigation Buttons in VueJs

In my ticket processing application I currently have a back and forward button contained in my TicketRunner.vue Component, I would like to change it so that these buttons only appear if I have an associated case file, for which I've used V-If:
TicketRunner.Vue
<div class="level nav-btns" v-if='!currentTicketCaseFiles.length'>
<div class="buttons has-addons level-left">
<b-button
#click.prevent="navGoPrev()"
:disabled="currentStepIndex === 0 || navWaiting"
size="is-medium"
>
</div>
export default {
name: 'TicketRunner',
mixins: [NavStepsByIndexMixin()],
components: {
StagePresenter,
CaseFilesStage,
ParticipantsStage,
AttachmentsStage,
CaseFilesRunner,
TicketContextButtons,
},
data: function() {
return {
firstComponentsInitialization: true,
loadingConfirm: false,
confirmationModalActive: false,
confirmationSucceeded: undefined
}
},
props: {
ticketId: {
type: Number,
required: true,
},
},
provide() {
return {
contextButtons: {
capture: (name, callback, title) => this.$refs['contextButtons'].captureButton(name, callback, title),
release: (name) => this.$refs['contextButtons'].releaseButton(name),
enable: (name) => this.$refs['contextButtons'].enableButton(name),
disable: (name) => this.$refs['contextButtons'].disableButton(name),
},
};
},
computed: {
...mapGetters(['currentTicket', 'ticketCaseFiles', 'allCurrentTicketAttachments', 'currentTicketCaseFileNotAssociated',
'currentRequesterType', 'currentTicketStage', 'lastCaseFile']),
caseFiles() {
return this.ticketCaseFiles(this.ticketId);
},
ticketHasAttachments() {
return this.allCurrentTicketAttachments.length > 0;
},
isTicketAssociatedWithCaseFile() {
return !this.currentTicketCaseFileNotAssociated;
},
isFirstNavInitializationInProgress() {
return !this.navReady && this.firstComponentsInitialization;
},
isShowAttachmentsStep() {
return this.ticketHasAttachments && this.currentRequesterType !== 'unknown' &&
(this.isFirstNavInitializationInProgress || this.isTicketAssociatedWithCaseFile)
},
isCurrentTicketResolved() {
return this.currentTicket.status === 'resolved';
},
islastStep() {
return this.navLastStep() && this.lastCaseFile;
}
},
watch: {
ticketId(){
this.navigator.reset();
},
navReady() {
this.moveForwardIfReady();
this.firstComponentsInitialization = false;
}
},
methods: {
...mapActions(['confirmTicket']),
moveForwardIfReady() {
if (this.navigator.currentIndex === 0 && this.firstComponentsInitialization) {
let steps = 0
const step_names = ['case_files_stage']
for(const [_idx, name] of step_names.entries()) {
const ref_name = `step[${name}]`;
if (this.$refs.hasOwnProperty(ref_name) && this.$refs[ref_name].navReady) {
steps += 1
} else {
break
}
}
this.navigator.currentIndex += steps
}
},
confirm() {
this.$buefy.dialog.confirm({
message: this.t('tickets.stages.confirmation.simplified_confirm_reply'),
onConfirm: () => this.confirmStep()
})
},
async confirmStep() {
this.loadingConfirm = true;
const promise = this.confirmTicket(this.ticketId);
return promise.then((response) => {
this.confirmationModalActive = true;
this.confirmationSucceeded = true;
return true; // true is correct here. for goNext it makes parent to stay on on the current step
}).catch(() => {
this.confirmationModalActive = true;
this.confirmationSucceeded = false;
return true; // true is correct here. for goNext it makes parent to stay on on the current step
}).finally(() => this.loadingConfirm = false);
},
},
};
I then receive the following Console Error:
[Vue warn]: Property or method "currentTicketCaseFiles" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
I know that "!currentTicketCaseFiles.length" works successfully in the Component CaseFilesStage.vue, which makes me believe I should somehow connect the two? But importing it doesn't seem right to me either. I'm not quite sure how to tackle this issue as I'm quite new at VueJS, and would be happy for any pointers. I'll attach the CaseFilesStage.vue Component below.
CaseFilesStage.vue
<template>
<div class="hero">
<div class="block">
<template v-if="!currentTicket.spamTicket">
<b-field>
<b-input
v-model="filter"
:loading="loading"
:placeholder="t('tickets.stages.case_files.search.tooltip')"
v-on:keyup.enter.native="searchCaseFiles"
type="search"
icon="search"
:class="{ 'preview-enabled': showAttachmentsPreview}"
/>
</b-field>
<template v-if="foundCaseFiles.length">
<h4 class="title is-4 table-title">{{ t('tickets.stages.case_files.search.table_title') }}</h4>
<CaseFilesSearchTable
:case-files="foundCaseFilxes"
:found-by-data-points="foundCaseFilesByParticipant"
:show-header="true"
v-slot="cf">
<b-checkbox v-if="cfBelongsToCurrentTicket(cf.id)" :disabled="true" :value="true"></b-checkbox>
<b-checkbox v-else #input="onFoundCaseFile(cf.id, $event)"></b-checkbox>
</CaseFilesSearchTable>
</template>
<div v-else-if="lookupStatus === 'notFound'">
{{ t('tickets.stages.case_files.search.not_found') }}
<!-- display button here if above is activated -->
</div>
</template>
</div>
<template v-if='currentTicketCaseFiles.length'>
<h4 class="title is-4 table-title">{{ t('tickets.stages.case_files.table_title') }}</h4>
<CaseFilesTable :case-files="currentTicketCaseFiles" :show-header="true" v-slot="cf">
<DeleteButton
:model-id="cf.id"
modelName="CaseFile" >
</DeleteButton>
</CaseFilesTable>
</template>
</div>
</template>
<script>
import CaseFilesTable from '../tables/CaseFilesTable';
import CaseFilesSearchTable from '../tables/CaseFilesSearchTable';
import DeleteButton from '../../../../shared/components/controls/DeleteButton';
import { mapGetters, mapActions } from 'vuex';
import { mapServerActions } from "../../../../../../_frontend_infrastructure/javascript/lib/crudvuex_new";
export default {
name: 'CaseFilesStage',
data() {
return {
lookupStatus: 'waitingInput',
filter: '',
waiting: {},
foundCaseFiles: [],
foundCaseFilesByParticipant: {}
};
},
components: {
CaseFilesTable,
CaseFilesSearchTable,
DeleteButton
},
computed: {
...mapGetters(
['currentTicketCaseFiles', 'currentTicketCaseFileNotAssociated', 'currentTicket', 'showAttachmentsPreview']
),
loading() {
return this.lookupStatus === 'waitingServer';
},
allCaseFilesMix(){
this.currentTicketCaseFiles + this.foundCaseFiles
},
foundCaseFilesEx() {
return this.foundCaseFiles.filter((x) => !this.cfBelongsToCurrentTicket(x.id))
},
checkboxValue() {
if(!this.currentTicketCaseFileNotAssociated) {
return null;
}
return true;
},
navReady() {
return this.currentTicket.spamTicket || this.currentTicketCaseFiles.length > 0 || this.checkboxValue;
},
markSpam: {
get: function() {
return this.currentTicket.spamTicket
},
set: function(val) {
return this.updateTicket([this.currentTicket.id, { spam_ticket: val }]);
},
}
},
methods: {
...mapActions(['updateTicket']),
...mapServerActions(['createCaseFile', 'deleteCaseFile']),
cfBelongsToCurrentTicket(id){
return this.currentTicketCaseFiles.map((x) => x.caseFileId).includes(id);
},
cantAssignCaseFileCheckbox(isChecked){
if(isChecked) {
this.createCaseFile({ isCfNotAssociated: true });
} else {
this.deleteCaseFile(this.currentTicketCaseFileNotAssociated);
}
},
onFoundCaseFile(id, useIt){
console.log("onFoundCaseFile: ", id, useIt);
if(useIt) {
this.createCaseFile({ caseFileId: id });
} else {
this.deleteCaseFile(this.currentTicketCaseFiles.find({ caseFileId: id }));
}
},
searchCaseFiles() {
const newData = this.filter;
if (newData.length < 3) { // TODO: some smarter condition here
this.foundCaseFiles = [];
this.lookupStatus = 'waitingInput';
return;
}
this.lookupStatus = 'waitingServer';
this.$axios.get('case_files', { params: { "case_files.filter" : newData } })
.then((response) => {
this.foundCaseFiles = response.data.caseFilesSearchResult.caseFiles;
this.foundCaseFilesByParticipant = response.data.caseFilesSearchResult.foundByPrivateInfo;
if(this.foundCaseFiles.length > 0) {
this.lookupStatus = 'success';
} else {
this.lookupStatus = 'notFound';
}
}).catch(() => this.lookupStatus = 'error');
}
},
};
</script>
</style>
Add this to your TicketRunner.vue Component script:
computed: {
...mapGetters(['currentTicketCaseFiles'])
}

[Framework7 Vuejs]Binding asyn data to template with v-for

I want to display total views for each id (1, 2, 3) by call api use axios like this:
<f7-block>
<f7-col
:key="index"
v-for="(items, index) in list">
Total views: {{countView(items.id)}}
</f7-col>
export default {
data(){
list: [];
// list = [{id: 1}, {id: 2}, {id: 3}]
},
methods(){
async countView(id){
let url = 'xxx';
let filter = {
where: {
quizId: id
}
}
try{
let res = await axios.get(url, filter);
return res.data.countViews;
} catch(error) {
}
}
}
}
How to use vue async data to display number of views instead {} ?
There is a better way, which is creating a custom component for each item. Then calling countView inside each custom component:
TotalView.vue
<template>
<span v-if="count !== null">
{{ count }}
</span>
</template>
<script>
export default {
name: 'TotalView'
props: ['itemId'],
data: () => ({
count: null
}),
created() {
this.countView(this.itemId)
},
methods: {
async countView(id){
let url = 'xxx';
let filter = {
where: {
quizId: id
}
}
try{
let res = await axios.get(url, filter);
this.count = res.data.countViews
} catch(error) {
}
}
}
}
</script>
and use that in your component:
<f7-block>
<f7-col
:key="index"
v-for="(items, index) in list">
Total views: <total-view :itemId="items.id" />
</f7-col>

Updating a prop inside a child component so it updates on the parent container too

So I have a simple template like so:
<resume-index>
<div v-for="resume in resumes">
<resume-update inline-template :resume.sync="resume" v-cloak>
//...my forms etc
<resume-update>
</div>
<resume-index>
Now, inside the resume-updatecomponent I am trying to update the prop on the inside so on the outside it doesn't get overwritten, my code is like so;
import Multiselect from "vue-multiselect";
import __ from 'lodash';
export default {
name: 'resume-update',
props: ['resume'],
components: {
Multiselect
},
data: () => ({
form: {
name: '',
level: '',
salary: '',
experience: '',
education: [],
employment: []
},
submitted: {
form: false,
destroy: false,
restore: false
},
errors: []
}),
methods: {
update(e) {
this.submitted.form = true;
axios.put(e.target.action, this.form).then(response => {
this.resume = response.data.data
this.submitted.form = false;
}).catch(error => {
if (error.response) {
this.errors = error.response.data.errors;
}
this.submitted.form = false;
});
},
destroy() {
this.submitted.destroy = true;
axios.delete(this.resume.routes.destroy).then(response => {
this.resume = response.data.data;
this.submitted.destroy = false;
}).catch(error => {
this.submitted.destroy = false;
})
},
restore() {
this.submitted.restore = true;
axios.post(this.resume.routes.restore).then(response => {
this.resume = response.data.data;
this.submitted.restore = false;
}).catch(error => {
this.submitted.restore = false;
})
},
reset() {
for (const prop of Object.getOwnPropertyNames(this.form)) {
delete this.form[prop];
}
}
},
watch: {
resume: function() {
this.form = this.resume;
},
},
created() {
this.form = __.cloneDeep(this.resume);
}
}
When I submit the form and update the this.resume I get the following:
[Vue warn]: Avoid mutating a prop directly since the value will be
overwritten whenever the parent component re-renders. Instead, use a
data or computed property based on the prop's value. Prop being
mutated: "resume"
I have tried adding computed to my file, but that didn't seem to work:
computed: {
resume: function() {
return this.resume
}
}
So, how can I go about updating the prop?
One solution:
simulate v-model
As Vue Guide said:
v-model is essentially syntax sugar for updating data on user input
events, plus special care for some edge cases.
The syntax sugar will be like:
the directive=v-model will bind value, then listen input event to make change like v-bind:value="val" v-on:input="val = $event.target.value"
So the steps:
create one prop = value which you'd like to sync to parent component
inside the child component, create one data porperty=internalValue, then uses Watcher to sync latest prop=value to data property=intervalValue
if intervalValue change, emit one input event to notice parent component
Below is one simple demo:
Vue.config.productionTip = false
Vue.component('container', {
template: `<div>
<p><button #click="changeData()">{{value}}</button></p>
</div>`,
data() {
return {
internalValue: ''
}
},
props: ['value'],
mounted: function () {
this.internalValue = this.value
},
watch: {
value: function (newVal) {
this.internalValue = newVal
}
},
methods: {
changeData: function () {
this.internalValue += '#'
this.$emit('input', this.internalValue)
}
}
})
new Vue({
el: '#app',
data () {
return {
items: ['a', 'b', 'c']
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
<p>{{items}}
<container v-for="(item, index) in items" :key="index" v-model="items[index]">
</container>
</div>
</div>
or use other prop name instead of value (below demo use prop name=item):
Also you can use other event name instead of event name=input.
other steps are similar, but you have to $on the event then implement you own handler like below demo.
Vue.config.productionTip = false
Vue.component('container', {
template: `<div>
<p><button #click="changeData()">{{item}}</button></p>
</div>`,
data() {
return {
internalValue: ''
}
},
props: ['item'],
mounted: function () {
this.internalValue = this.item
},
watch: {
item: function (newVal) {
this.internalValue = newVal
}
},
methods: {
changeData: function () {
this.internalValue += '#'
this.$emit('input', this.internalValue)
this.$emit('test-input', this.internalValue)
}
}
})
new Vue({
el: '#app',
data () {
return {
items: ['a', 'b', 'c']
}
},
methods: {
syncChanged: function (target, index, newData) {
this.$set(target, index, newData)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<div>
Event Name=input
<p>{{items}}</p>
<container v-for="(item, index) in items" :key="index" :item="item" #input="syncChanged(items, index,$event)">
</container>
</div>
<hr> Event Name=test-input
<container v-for="(item, index) in items" :key="index" :item="item" #test-input="syncChanged(items, index,$event)">
</container>
</div>
I usually use vuex to manage variables that I will be using in multiple components and like the error says, load them in the various components using the computed properties. Then use the mutations property of the store object to handle changes
In component files
computed: {
newProfile: {
get() {
return this.$store.state.newProfile;
},
set(value) {
this.$store.commit('updateNewProfile', value);
}
},
In the vuex store
state: {
newProfile: {
Name: '',
Website: '',
LoginId: -1,
AccountId: ''
}
},
mutations: {
updateNewProfile(state, profile) {
state.newProfile = profile;
}
}

Reload Data of vue-tables-2 (Vuex)

Module: https://github.com/matfish2/vue-tables-2
I'm creating a CRUD app. How can I reload the data fetched via Ajax call in vue-tables-2? I wanted to reload the table after an update statement is executed somewhere in my app.
Vue-tables is using vuex in my setup.
<v-server-table
name="UserAdmin" url="admin/master/?format=json" :columns="columns" :options="options">
</v-server-table>
EDIT: Added Javascript code of the table for data properties.
export default {
data() {
return {
columns: ['ID','NAME', 'POSITION', 'APPLICATIONS','DESCRIPTION','STATUS','ENCODED_BY'],
options: {
responseAdapter: (resp) => {
resp = resp.map(item => ({
ID: item.ID,
FK_ID: item.FK_ID,
NAME: `${item.FIRSTNAME} ${item.LASTNAME}`,
POSITION: item.POSITION,
APPLICATIONS: item.APPLICATIONS,
DESCRIPTION: item.DESCRIPTION,
STATUS: item.STATUS,
ENCODED_BY: item.ENCODED_BY,
TOTAL: item.TOTAL
}));
let count;
if(resp[0] != null) {
count = resp[0]['TOTAL']
}
else {
count = 0
}
return {
data: resp,
count: count
}
},
headings: {
'ID': <span># </span>,
'NAME':'Name',
'POSITION':'Position',
'APPLICATIONS':'Applications',
'DESCRIPTION':'Description',
'STATUS': 'Status',
'ENCODED_BY':'Encoded By',
'edit': 'Options'
},
columnsClasses: {
ID: 'col-md-1',
NAME:'col-md-2 pointer',
POSITION: 'col-md-2',
APPLICATIONS: 'col-md-2',
DESCRIPTION: 'col-md-2',
STATUS: 'col-md-1',
ENCODED_BY: 'col-md-2',
},
templates: {
NAME: (h, row) => {
return <a on-click={ () => this.setUpdateID(row) }>{row.NAME}</a>
},
APPLICATIONS: (h,row) => {
return (<ul>{JSON.parse(row.APPLICATIONS).map((val)=>(<li>{val}</li>))}</ul>);
},
STATUS: (h, row) => {
if(row.STATUS == 1) {
return <span class="label label-success">Active</span>
}
else if(row.STATUS == 0) {
return <span class="label label-danger">Inactive</span>
}
}
},
},
}
},
methods: {
setUpdateID: function(row) {
this.$store.commit('SET_UPDATE_ID', row.FK_ID);
}
}
}
As documented you should use the refresh method.
You can read about refs here
<v-server-table ref="table"
name="UserAdmin" url="admin/master/?format=json" :columns="columns" :options="options">
</v-server-table>
Javascript:
methods:{
onUpdate() {
this.$refs.table.refresh();
}
}
for reloading the vuetable with updated data you have two way:
1.
select the vuetable component with $refs in your code and then calling refresh method , something like this:
html file:
<v-server-table ref="userAdminVueTable"
name="UserAdmin" url="admin/master/?format=json" :columns="columns" :options="options">
js file:
this.$refs.userAdminVueTable.refresh()
2.
When you have your data you can call setData method for your vuetable.
this.vuetable.setData(updatedData);
in below i write an example for you, you can get inspire from that:
this.Service.GetAllRecords().then(result => {
this.vuetable.setData(result);
}).catch(e => {
this.showAlert = true
this.message = ` Exception : ${e}`
})
}
You don't need to refresh it, if you refresh than state would be clear. You can use bellow example
methods:{
onUpdate(rowIndex) {
this.$refs.table.data.splice(rowIndex, 1);
}
}
<v-server-table ref="table"
name="UserAdmin" url="admin/master/?format=json" :columns="columns" :options="options">
</v-server-table>