问题描述
我一直在寻找一种在 Bootstrap Vue 表上拖放行的方法。 我在这里找到了一个工作版本:
我试图将此代码实现到我自己的表中:
模板:
<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>
?
编辑: :
1楼
karthickj25
3
已采纳
2019-02-14 04:18:28
在行中const table = el.querySelector('table');
您正在尝试获取表格元素。
var el
是表格元素。
这就是为什么当您使用querySelector
时它返回 null
分配正确的表变量后,错误消失
const table = el;
table._sortable = createSortable(table.querySelector("tbody"), binding.value, vnode);
2楼
xiser
-2
2020-05-25 11:55:30
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>