我一直在寻找一种在Bootstrap Vue表上拖放行的方法。 我可以在这里找到有效的版本:Codepen
我试图将这段代码实现到我自己的表中:
模板:
<b-table v-sortable="sortableOptions" @click="(row) => $toast.open(`Clicked ${row.item.name}`)" :per-page="perPage" :current-page="currentPage" striped hover :items="blis" :fields="fields" :filter="filter" :sort-by.sync="sortBy" :sort-desc.sync="sortDesc" :sort-direction="sortDirection" @filtered="onFiltered">
<template slot="move" slot-scope="row">
<i class="fa fa-arrows-alt"></i>
</template>
<template slot="actions" slot-scope="row">
<b-btn :href="'/bli/'+row.item.id" variant="light" size="sm" @click.stop="details(cell.item,cell.index,$event.target)"><i class="fa fa-pencil"></i></b-btn>
<b-btn variant="light" size="sm" @click.stop="details(cell.item,cell.index,$event.target)"><i class="fa fa-trash"></i></b-btn>
</template>
<template slot="priority" slot-scope="row">
<input v-model="row.item.priority" @keyup.enter="row.item.focussed = false; updatePriority(row.item), $emit('update')" @blur="row.item.focussed = false" @focus="row.item.focussed = true" class="form-control" type="number" name="priority" >
</template>
</b-table>
脚本:
import Buefy from 'buefy';
Vue.use(Buefy);
const createSortable = (el, options, vnode) => {
return Sortable.create(el, {
...options
});
};
const sortable = {
name: 'sortable',
bind(el, binding, vnode) {
const table = el.querySelector('table');
table._sortable = createSortable(table.querySelector('tbody'), binding.value, vnode);
}
};
export default {
name: 'ExampleComponent',
directives: { sortable },
data() {
let self = this;
return {
blis: [],
currentPage: 1,
perPage: 10,
pageOptions: [ 5, 10, 15 ],
totalRows: 0,
sortBy: null,
sortDesc: false,
sortDirection: 'asc',
sortableOptions: {
chosenClass: 'is-selected'
},
filter: null,
modalInfo: { title: 'Title', content: 'priority' },
fields: [
{
key: 'move',
sortable: true
},
///...rest of the fields
]
}
};
现在我已经收到此错误:指令可排序绑定挂钩中的错误:“ TypeError:无法读取null的属性'querySelector'”
为什么找不到<tbody>
?
答案 0 :(得分:1)
在const table = el.querySelector('table');
行中,您尝试获取table元素。 var el
是table元素。这就是为什么当您使用querySelector
分配正确的表变量后,错误消失
const table = el;
table._sortable = createSortable(table.querySelector("tbody"), binding.value, vnode);
答案 1 :(得分:-2)
new Vue({
el: "#app",
directives: {
sortable: {
bind(el, binding, vnode) {
let self =el
Sortable.create(el.querySelector('tbody'),{
...binding.value,
vnode:vnode,
onEnd: (e) => {
let ids = el.querySelectorAll("span[id^=paper_]")
let order = []
for (let i = 0; i < ids.length; i++) {
let item = JSON.parse(ids[i].getAttribute('values'))
//extract items checkbox onChange v-model
let itemInThisData = vnode.context.items.filter(i => i.id==item.id)
order.push({
id:item.id,
paper: item.paper,
domain:item.domain,
platform: item.platform,
country:item.country,
sort_priority: item.sort_priority,
selectpaper:itemInThisData[0].selectpaper
})
}
binding.value = []
vnode.context.items = []
binding.value = order
vnode.context.items = order
console.table(vnode.context.items)
},
});
},
}
},
mounted() {
this.totalRows = this.items?this.items.length: 0
},
methods:{
onFiltered(filteredItems) {
// Trigger pagination to update the number of buttons/pages due to filtering
this.totalRows = filteredItems.length
this.currentPage = 1
},
log(){
console.table(this.items)
console.log(this)
},
},
data(){
return {
rankOption:'default',
totalRows: 1,
currentPage: 1,
filter: null,
filterOn:[],
sortBy:'paper',
sortDesc: false,
sortableOptions: {
chosenClass: 'is-selected'
},
perPage: this.results_per_page==='Todo' ? this.items.length : this.results_per_page?this.results_per_page:50,
pageOptions: [10, 50, 100, 500,'Todo'],
sortDirection: 'asc',
fields : [
{ key: 'paper', label: 'Soporte', sortable: true},
{ key: 'domain', label: 'Dominio', sortable: true},
{ key: 'platform', label: 'Medio', sortable: true},
{ key: 'country', label: 'País', sortable: true},
{ key: 'sort_priority', label: 'Rank', sortable: true},
{ key: 'selectpaper', label: 'Selección', sortable: true},
],
items : [
{
id:12,
paper: 'Expansion',
domain:'expansion.com',
platform: 'p',
country:'España',
sort_priority: '',
selectpaper:false
},
{
id:13,
paper: 'El economista',
domain:'eleconomista.es',
platform: 'p',
country:'España',
sort_priority: '',
selectpaper:false
},
{
id:14,
paper: 'El país',
domain:'elpais.es',
platform: 'p',
country:'España',
sort_priority: '',
selectpaper:false
}
]
}
}
})
<div id="app">
<template id="">
<b-table
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
v-sortable="items"
show-empty
small
stacked="md"
:items="items"
:fields="fields"
:current-page="currentPage"
:per-page="perPage"
:filter="filter"
:filterIncludedFields="filterOn"
:sort-direction="sortDirection"
@filtered="onFiltered"
>
<template v-slot:cell(selectpaper)="row">
<span :id="'paper_'+row.item.id" :values="JSON.stringify(row.item)"></span>
<b-form-group>
<input type="checkbox" @change="log" v-model="row.item.selectpaper" />
</b-form-group>
</template>
<template v-slot:cell(sort_priority)="row" v-if="rankOption==='foreach-row'">
<b-form-group>
<b-form-input type="number" @change="log"
size="sm" placeholder="Rank" v-model="row.item.sort_priority">
</b-form-input>
</b-form-group>
</template>
</b-table>
</template>
</div>
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>