How to Implement Delete Data in Vue-Tables-2? - vue.js

I am confused how to implement delete in vue-tables-2. I used this library https://www.npmjs.com/package/vue-tables-2
This is my code
HTML
<v-client-table :columns="columns" v-model="data" :options="options">
<div slot="action">
<button #click="erase" class="btn btn-danger">Delete</button>
</div>
<div slot="nomor" slot-scope>
<span v-for="t in nomer" :key="t">{{t}}</span>
</div>
<div slot="category_name" slot-scope="{row}">{{row.category_name}}</div>
</v-client-table>
Vue Js
<script>
var config = {
"PMI-API-KEY": "erpepsimprpimaiy"
};
export default {
name: "user-profile",
data() {
return {
nomer: [],
columns: ["nomor", "category_name", "action"],
data: [],
options: {
headings: {
nomor: "No",
category_name: "Category Name",
action: "Action"
},
filterByColumn: true,
sortable: ["category_name"],
filterable: ["category_name"],
templates: {
erase: function(h, row, index) {
return <delete id={row.data.category_id}></delete>;
}
}
}
};
},
methods: {
load() {
this.$http({
url: "api/v1/news_category/get_all_data",
method: "post",
headers: config
}).then(res => {
this.data = res.data.data;
});
},
del() {
this.$http({
url: "api/v1/news_category/delete",
method: "post",
headers: config
}).then(res => {
console.log("success");
});
}
},
mounted() {
this.load();
}
};
</script>
When I run the code, I got error "erase not defined". I wanna implement like the documentation which you can see at https://www.npmjs.com/package/vue-tables-2#vue-components

Your template is missing the erase function which means you have to define erase as your components method, just like that:
methods: {
erase(h, row, index) {
return <delete id={row.data.category_id}></delete>;
}
}

Related

Default props value are not selected in vue3 options api

I created a select2 wrapper in vue3 with options API everything working fine but the problem is that when getting values from calling API it's not selected the default value in the select2 option. but when I created a static array of objects it does. I don't know why it's working when it comes from the API
Parent Component
Here you can I passed the static options array in options props and my selected value is 2 and it's selected in my Select2 component, but when passed formattedCompanies it's not which is the same format as the static options array then why is not selected any reason here..?
<template>
<Form #submitted="store()" :processing="submitting">
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label>Company Name</label>
<Select2
:options="options"
v-model="selected"
placeholder="Select Company"
/>
<ValidationError :errors="errors" error-key="name" />
</div>
</div>
</div>
</Form>
</template>
<script>
import Form from "#/components/Common/Form";
import Select2 from "#/components/Common/Select2";
export default {
components: {
Select2,
Form
},
data() {
return {
selected : 2,
companies : [],
options: [ // static array
{ id: 1, text: 'hello' },
{ id: 2, text: 'hello2' },
{ id: 3, text: 'hello3' },
{ id: 4, text: 'hello4' },
{ id: 5, text: 'hello5' },
],
}
},
mounted() {
this.getAllMedicineCompanies()
},
computed:{
formattedCompanies() {
let arr = [];
this.companies.forEach(item => {
arr.push({id: item.id, text: item.name})
});
return arr;
}
},
methods: {
getAllMedicineCompanies(){
axios.get('/api/get-data?provider=companies')
.then(({ data }) => {
this.companies = data
})
},
}
}
</script>
Select2 Component
Here is what my select2 component look like, did I do anything wrong here, please anybody help me
<template>
<select class="form-control">
<slot/>
</select>
</template>
<script>
export default {
name: "Select2",
props: {
options: {
type: [Array, Object],
required: true
},
modelValue: [String, Number],
placeholder: {
type: String,
default: "Search"
},
allowClear: {
type: Boolean,
default: true
},
},
mounted() {
const vm = this;
$(this.$el)
.select2({ // init select2
data: this.options,
placeholder: this.placeholder,
allowClear: this.allowClear
})
.val(this.modelValue)
.trigger("change")
.on("change", function () { // emit event on change.
vm.$emit("update:modelValue", this.value);
});
},
watch: {
modelValue(value) { // update value
$(this.$el)
.val(value)
.trigger("change");
},
options(options) { // update options
$(this.$el)
.empty()
.select2({data: options});
},
},
destroyed() {
$(this.$el)
.off()
.select2("destroy");
}
}
</script>
Probably when this Select2 mounted there is no companies. It is empty array after that it will make API call and it it populates options field and clear all options.
Make:
companies : null,
Change it to
<Select2
v-if="formattedCompanies"
:options="formattedCompanies"
v-model="selected"
placeholder="Select Company"
/>
It should be like this:
<template>
<Form #submitted="store()" :processing="submitting">
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label>Company Name</label>
<Select2
v-if="formattedCompanies"
:options="formattedCompanies"
v-model="selected"
placeholder="Select Company"
/>
<ValidationError :errors="errors" error-key="name" />
</div>
</div>
</div>
</Form>
</template>
<script>
import Form from "#/components/Common/Form";
import Select2 from "#/components/Common/Select2";
export default {
components: {
Select2,
Form
},
data() {
return {
selected : 2,
companies : null,
options: [ // static array
{ id: 1, text: 'hello' },
{ id: 2, text: 'hello2' },
{ id: 3, text: 'hello3' },
{ id: 4, text: 'hello4' },
{ id: 5, text: 'hello5' },
],
}
},
mounted() {
this.getAllMedicineCompanies()
},
computed:{
formattedCompanies() {
let arr = [];
this.companies.forEach(item => {
arr.push({id: item.id, text: item.name})
});
return arr;
}
},
methods: {
getAllMedicineCompanies(){
axios.get('/api/get-data?provider=companies')
.then(({ data }) => {
this.companies = data
})
},
}
}
</script>
The problem was that my parent component and Select2 component mounted at the same time that's why my computed value is not initialized so the selected value is not selected in the option,
problem solved by setTimeOut function in mounted like this
Select2 Component
<script>
mounted() {
const vm = this;
setTimeout(() => {
$(this.$el)
.select2({ // init select2
data: this.options,
placeholder: this.placeholder,
allowClear: this.allowClear
})
.val(this.modelValue)
.trigger("change")
.on("change", function () { // emit event on change.
vm.$emit("update:modelValue", this.value);
});
}, 500)
},
</script>

Set focus on input element with Vue

I try to code an inline edit element. I like to have the focus on the input, after click. Here my code:
<span v-show="!name.edit" #click="toggleEdit(this, name)">{{name.val}}</span>
<input type="text"
v-model="name.val"
v-show="name.edit"
v-on:blur=" saveEdit(this, name)"
>
</div>
data: function () {
return {
name: {
val: '',
edit: false
},
}
},
methods: {
...mapMutations([
]),
toggleEdit: function(ev, obj){
obj.edit = !obj.edit;
console.log(obj)
if(obj.edit){
Vue.nextTick(function() {
ev.$$.input.focus();
})
}
},
saveEdit: function(ev, obj){
//save your changes
this.toggleEdit(ev, obj);
}
},
But it's still not working.
Try puting $ref in that specific input and vue.nextTick should be this.$nextTick:
like this:
<input type="text"
ref="inputVal"
v-model="name.val"
v-show="name.edit"
v-on:blur=" saveEdit(this, name)"
>
this.$nextTick(function() {
this.$refs.inputVal.focus();
});
https://codesandbox.io/s/keen-sutherland-euc3c
Usually for dynamic elements i would do this:
<template>
<div>
<template v-for="name in names">
<span :key="name.name" v-show="!name.edit" #click="toggleEdit(this, name)">{{name.val}}</span>
<input
:key="name.name"
type="text"
:ref="name.val"
v-model="name.val"
v-show="name.edit"
v-on:blur=" saveEdit(this, name)"
>
</template>
</div>
</template>
<script>
export default {
name: "App",
components: {},
data: function() {
return {
names: [
{
val: "TEST1",
edit: true
},
{
val: "TEST2",
edit: true
},
{
val: "TEST3",
edit: true
}
]
};
},
methods: {
toggleEdit: function(ev, obj) {
obj.edit = !obj.edit;
console.log(obj);
if (obj.edit) {
this.$nextTick(function() {
this.$refs[`${obj.val}`][0].focus();
});
}
},
saveEdit: function(ev, obj) {
//save your changes
this.toggleEdit(ev, obj);
}
}
};
</script>

Vuejs Reactivity on Set Value

I have a custom table with actions via a modal popup that set values on Rows. Things are mostly working great (Updates to Foo and Bar get sent to the backend and are set in a database, reload of the page pulls the data from the database and shows foo/bar were correctly set). The only not-great part is on setting of Foo, the value in the table does not get updated. Bar gets updated/is reactive. (the template uses foo.name and bar.id). Does anyone have any ideas on how to get Foo to update in the table? I've changed the moustache template to use {{ foo.id }} and it updates, but I need foo.name.
<template>
<div>
<c-dialog
v-if="foo_modal"
title="Set Foo"
:actions="foo_modal_options.actions"
#cancel="foo_modal = null">
<slot>
<div class="form-group">
<label>Foo:</label>
<select class="form-control" v-model="foo_modal.thing.foo.id">
<option v-for="foo in foos" :key="foo.id" :value="foo.id">{{ foo.name }}</option>
</select>
</div>
</slot>
</c-dialog>
<c-dialog
v-if="bar_modal"
title="Set Rod/Stick"
:actions="bar_modal_options.actions"
#cancel="bar_modal = null">
<slot>
<div class="form-group">
<label>Rod:</label>
<select class="form-control" v-model="bar_modal.thing.rod.id">
<option v-for="bar in bars" :key="bar.id" :value="bar.id" v-if="bar.type === 'rod'">{{ bar.id }}</option>
</select>
</div>
<div class="form-group">
<label>Stick:</label>
<select class="form-control" v-model="bar_modal.thing.stick.id">
<option v-for="bar in bars" :key="bar.id" :value="bar.id" v-if="bar.type === 'stick'">{{ bar.id }}</option>
</select>
</div>
</slot>
</c-dialog>
<c-table-paginated
class="c-table-clickable"
:rows="grid.data"
:columns="grid.columns"
:actions="grid.actions"
:key="componentKey">
</c-table-paginated>
</div>
</template>
<script>
import fooModal from '../../components/fooModal.vue';
import barModal from '../../components/barModal.vue';
import CTablePaginated from "../../components/custom/cTable/cTablePaginated";
import cTooltip from '../../components/custom/cTooltip/cTooltip.vue';
import cDialog from '../../components/custom/cDialog/cDialog.vue';
import moment from 'moment';
export default {
components: { CTablePaginated, cTooltip, cDialog },
methods: {
loadData() {
let that = this;
that.$http.get('/things', { params: that.param || {} })
.then(function (things) {
that.things = things.data;
that.grid.data = that.things;
});
},
setBar(thing_id, options, cb) {
let that = this;
this.$http.patch(`/things/${thing_id}`, { rod_id: options.rod, stick_id: options.stick })
.then(function () {
cb();
});
},
setFoo(thing_id, options, cb) {
let that = this;
this.$http.patch(`/things/${thing_id}`, { foo_id: options.foo_id })
.then(function () {
cb();
})
},
},
data() {
return {
componentKey: 0,
things: null,
foos: [],
bars: [],
foo_modal: null,
foo_modal_options: {
actions: [
{
label: "Save",
class: "btn-primary",
action: (function (ctx) {
return function () {
const thing = ctx.foo_modal.thing;
const options = {
foo_id: thing.foo.id,
};
ctx.setFoo(thing.id, options, function () {
ctx.foo_modal = null;
});
}
})(this)
},
{
label: "Cancel",
action: (function (ctx) {
return function () {
ctx.foo_modal = null;
}
})(this)
}
]
},
bar_modal: null,
bar_modal_options: {
actions: [
{
label: "Save",
class: "btn-primary",
action: (function (ctx) {
return function () {
const thing = ctx.bar_modal.thing;
const options = {
rod: thing.rod.id,
stick: thing.stick.id
};
ctx.setBar(thing.id, options, function () {
ctx.bar_modal = null;
});
}
})(this)
},
{
label: "Cancel",
action: (function (ctx) {
return function () {
ctx.bar_modal = null;
}
})(this)
}
]
},
grid: {
data: [],
columns: [
{
label: "Foo",
value: function (row) {
if (!row.foo) return "No foo set";
return `${row.foo.name }`;
}
},
{
label: "Rod/Stick",
value: function (row) {
if (!row.rod && !row.stick) return "No rod/stick set";
if (!row.rod) return `No rod set/${row.stick.id}`;
if (!row.stick) return `${row.rod.id}/no stick set`;
return `${row.rod.id}/${row.stick.id}`;
}
}
],
actions: [
{
label: "Set Foo",
visible: function (thing) {
return !thing.active;
},
action: (function (ctx) {
return function (thing) {
if (!thing.foo) thing.foo = {};
ctx.foo_modal = {
thing: thing
};
}
})(this)
},
{
label: "Set Bar",
visible: function (thing) {
return !thing.active;
},
action: (function (ctx) {
return function (thing) {
if (!thing.rod) thing.rod = {};
if (!thing.stick) thing.stick = {};
ctx.bar_modal = {
thing: thing
};
}
})(this)
},
],
}
};
},
props: {
title: {
type: String
},
param: {
type: Object,
required: true
},
events: {
type: Object,
required: true
}
},
created() {
let that = this;
this.loadData();
this.$http.get('/bars')
.then(function (bars) {
that.bars = bars.data;
});
this.$http.get('/foos')
.then(function (foos) {
that.foos = foos.data;
});
},
}
</script>
There are two possibilities you can try both if any one of them can help you.
You can set value by using Vuejs this.$set method for deep reactivity. Click here.
You can use this.$nextTick(()=>{ // set your variable here }). Click here.

Vue-Slick and v-for with dynamic data

i'm using vue-slick to show my images..
i've tried every solution that i found.. but none is working.
here is my template:
<slick ref="slick" :options="slickOptions">
<img v-for="(item) in categories" :src="'/images/category/'+item.image_url" alt="" class="img-fluid" >
</slick>
and here is my scripts:
data () {
return {
categories:'',
slickOptions: {
dots: true,
infinite: false,
autoplay: false,
arrows : false,
draggable:true,
speed: 1000,
slidesToShow: 1,
slidesToScroll: 1,
},
}
},
mounted() {
let _this = this;
axios({
method: 'post',
url: '/api/category',
data : {'name' : _this.name}
}).then( (response)=> {
console.log(response.data.data);
_this.categories = response.data.data;
}).catch((error) => {
console.log(error.response)
});
},
methods:{
next() {
this.$refs.slick.next();
},
prev() {
this.$refs.slick.prev();
},
reInit() {
this.$refs.slick.reSlick()
}
},
and only loading the image, and the slick is not working...!!?
I have faced the same issue, and what I did to solve this is to put the
v-if="categories.length > 0" on the <slick> tag.
It make the slick won't be created before the data that we want to display contains the data first.
Use below code to reinit slick, and call on success function of response
reInit() {
let currIndex = this.$refs.slick.currentSlide()
this.$refs.slick.destroy()
this.$nextTick(() => {
this.$refs.slick.create()
this.$refs.slick.goTo(currIndex, true)
})
}
I'm assuming your Axios is returning data with the structure you are looking for.
I'm also assuming you are using the vue-slick component and not slick.
You should iterate through a DIV like stated in the documentation. Without Axios, I did this:
In template:
<slick ref="slick" :options="slickOptions">
<div>Escolhe uma configuraĆ§Ć£o...</div>
<div v-for="d in data1"><a class="inline" :href="d.image"><img :src="d.image" alt="">{{ d.text }}</a></div>
</slick>
In Javascript:
data: function() {
return {
data1: [
{ image: 'http://placehold.it/100x100', text: 'Config1' },
{ image: 'http://placehold.it/100x100', text: 'Config2' },
{ image: 'http://placehold.it/100x100', text: 'Config3' },
{ image: 'http://placehold.it/100x100', text: 'Config4' }
]
}

vee validate on custom select2 component not works

I try to use vee-validate on a custom component where if nothing selected on submit should show the validation error
the template looks as it follows
<div id="validate" class="container">
<form #submit.prevent="store()" data-vv-scope="time-off" autocomplete="off">
<div class="col-lg-6">
<div class="form-group">
<select2
:options="options"
placeholder='Select...'
v-validate="'required|in:sick, vacation'"
v-model="form.category"
id="categorywidget"
class="form-control">
</select2>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary pull-right">
Send Request
</button>
</div>
</div>
</div>
</form>
</div>
and here is my vue code
Vue.component('Select2', {
props: ['options', 'value', 'id', 'placeholder', 'clear'],
template: '<select><slot></slot></select>',
mounted: function () {
var vm = this
$(this.$el)
.select2({
data: this.options,
placeholder: this.placeholder,
theme: "bootstrap",
width: '100% !important',
dropdownAutoWidth : true,
allowClear: this.clear !== '' ? this.clear : false
})
.val(this.value)
.attr("id", this.id !== null ? this.id : Date.now() + Math.random() )
.trigger('change')
// emit event on change.
.on('change', function () {
vm.$emit('input', $(this).val())
})
},
watch: {
value: function (value) {
// update value
$(this.$el).val(value).trigger('change');
},
options: function (options) {
// update options
$(this.$el).select2({data: options})
}
},
destroyed: function () {
$(this.$el).off().select2('destroy')
}
});
Vue.use(VeeValidate)
new Vue({
el: '#validate',
data: {
form: {
scopes: [],
category: 'null',
daterange: '',
note: ''
},
options: [
{text: 'Vacation', id: 'vacation'},
{text: 'Sick', id: 'sick'},
{text: 'Not ok', id: 'not-ok'},
]
},
methods: {
store: function() {
this.$validator
.validateAll()
.then(function(response) {
alert('is ok!')
// Validation success if response === true
})
.catch(function(e) {
// Catch errors
alert('not ok!')
})
}
}
});
here is a pen what I created
https://codepen.io/anon/pen/gXwoQX?editors=1111
on submit null the validation is passes. what is wrong with this codes
There are issues raised on this subject in github - #590, #592.
None of them lead me to a solution, so I'd suggest a check inside the promise
.then(response => {
if(this.errors.items.length === 0) {
alert('is valid')
} else {
alert('is not valid')
}
A couple of other notes:
See below, catch() is technically the wrong place to handle validation errors, that should be inside the then(response) and when invalid response === false (but not working because of bug).
The catch() is probably for 'I blew up' errors.
.catch(function(e) {
// Catch errors
// alert('not valid') // don't process these here
})
Also this
v-validate="'required|in:sick, vacation'"
should be this (remove space before vacation)
v-validate="'required|in:sick,vacation'"