Skip to content

Commit 4467058

Browse files
Merge pull request #663 from SortableJS/scope-slot-new-syntax
Fix for issue #633
2 parents 8a0015a + c8aaa8d commit 4467058

File tree

3 files changed

+149
-2
lines changed

3 files changed

+149
-2
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<template>
2+
<div class="row">
3+
<div class="col-2">
4+
<div class="form-group">
5+
<div
6+
class="btn-group-vertical buttons"
7+
role="group"
8+
aria-label="Basic example"
9+
>
10+
<button
11+
class="btn btn-secondary"
12+
@click="add"
13+
>Add</button>
14+
<button
15+
class="btn btn-secondary"
16+
@click="remove"
17+
>Remove</button>
18+
<button
19+
class="btn btn-secondary"
20+
@click="clear"
21+
>Clear</button>
22+
</div>
23+
</div>
24+
</div>
25+
26+
<div class="col-6">
27+
<h3>Draggable</h3>
28+
29+
<draggable
30+
:list="list"
31+
:disabled="!enabled"
32+
class="list-group"
33+
ghost-class="ghost"
34+
>
35+
<div
36+
class="list-group-item"
37+
v-for="element in list"
38+
:key="element.name"
39+
>
40+
{{ element.name }}
41+
</div>
42+
43+
<template v-slot:header>
44+
<div>
45+
header slot
46+
</div>
47+
</template>
48+
49+
<template v-slot:footer>
50+
<div>
51+
footer slot
52+
</div>
53+
</template>
54+
</draggable>
55+
</div>
56+
57+
<rawDisplayer
58+
class="col-3"
59+
:value="list"
60+
title="List"
61+
/>
62+
</div>
63+
</template>
64+
65+
<script>
66+
import draggable from "@/vuedraggable";
67+
68+
let id = 1;
69+
export default {
70+
name: "slot-example",
71+
display: "Slot example",
72+
order: 1,
73+
debug: true,
74+
components: {
75+
draggable
76+
},
77+
data() {
78+
return {
79+
enabled: true,
80+
list: [
81+
{ name: "John", id: 0 },
82+
{ name: "Joao", id: 1 },
83+
{ name: "Jean", id: 2 }
84+
]
85+
};
86+
},
87+
methods: {
88+
clear: function() {
89+
this.list = [];
90+
},
91+
add: function() {
92+
this.list.push({ name: "Juan " + id, id: id++ });
93+
},
94+
remove: function() {
95+
this.list.pop();
96+
}
97+
}
98+
};
99+
</script>
100+
<style scoped>
101+
.buttons {
102+
margin-top: 35px;
103+
}
104+
105+
.ghost {
106+
opacity: 0.5;
107+
background: #c8ebfb;
108+
}
109+
</style>

src/vuedraggable.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,19 @@ function isTransition(slots) {
5555
return isTransitionName(componentOptions.tag);
5656
}
5757

58-
function computeChildrenAndOffsets(children, { header, footer }) {
58+
function getSlot(slot, scopedSlot, key) {
59+
return slot[key] || (scopedSlot[key] ? scopedSlot[key]() : undefined);
60+
}
61+
62+
function computeChildrenAndOffsets(children, slot, scopedSlot) {
5963
let headerOffset = 0;
6064
let footerOffset = 0;
65+
const header = getSlot(slot, scopedSlot, "header");
6166
if (header) {
6267
headerOffset = header.length;
6368
children = children ? [...header, ...children] : [...header];
6469
}
70+
const footer = getSlot(slot, scopedSlot, "footer");
6571
if (footer) {
6672
footerOffset = footer.length;
6773
children = children ? [...children, ...footer] : [...footer];
@@ -159,7 +165,8 @@ const draggableComponent = {
159165
this.transitionMode = isTransition(slots);
160166
const { children, headerOffset, footerOffset } = computeChildrenAndOffsets(
161167
slots,
162-
this.$slots
168+
this.$slots,
169+
this.$scopedSlots
163170
);
164171
this.headerOffset = headerOffset;
165172
this.footerOffset = footerOffset;

tests/unit/vuedraggable.spec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,4 +1209,35 @@ describe("draggable.vue when initialized with a transition group", () => {
12091209
})
12101210
})
12111211
});
1212+
1213+
describe("draggable.vue when initialized with header and footer scoped slots", () => {
1214+
beforeEach(() => {
1215+
resetMocks();
1216+
items = ["a", "b", "c"];
1217+
wrapper = shallowMount(draggable, {
1218+
attachToDocument: true,
1219+
propsData: {
1220+
list: items
1221+
},
1222+
attrs: {
1223+
sortableOption: "value",
1224+
"to-be-camelized": true
1225+
},
1226+
slots: {
1227+
default: items.map(item => `<div>${item}</div>`),
1228+
},
1229+
scopedSlots: {
1230+
header: "<header/>",
1231+
footer: "<footer/>"
1232+
},
1233+
});
1234+
vm = wrapper.vm;
1235+
props = vm.$options.props;
1236+
element = wrapper.element;
1237+
});
1238+
1239+
it("renders correctly", () => {
1240+
expect(wrapper.html()).toEqual(initialRender);
1241+
})
1242+
});
12121243
});

0 commit comments

Comments
 (0)