Skip to content

Commit af3cbb9

Browse files
authored
Merge pull request #71 from grapoza/treeviewnode-slots
Adds slots for node content
2 parents 34f96f3 + 2de33a4 commit af3cbb9

File tree

11 files changed

+489
-44
lines changed

11 files changed

+489
-44
lines changed

docs/demo/demos.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ Note that demos probably (definitely) won't work in IE due to the way the compon
66

77
- [Basic Checkbox Usage](basic.html)
88
- [Basic Radio Button Usage](radioBasic.html)
9-
- [Adding and Removing Nodes](addRemove.html)
9+
- [Adding and Removing Nodes](addRemove.html)
10+
- [Slots](slots.html)

docs/demo/slots.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export default [
2+
{
3+
id: 'node1',
4+
label: 'Checkbox Node',
5+
input: {
6+
type: 'checkbox',
7+
name: 'checkbox1'
8+
},
9+
state: {
10+
input: {
11+
value: false,
12+
disabled: false
13+
}
14+
},
15+
children: []
16+
},
17+
{
18+
id: 'node2',
19+
label: 'Radiobutton Node',
20+
input: {
21+
type: 'radio',
22+
name: 'radiobutton1'
23+
},
24+
state: {
25+
input: {
26+
value: false,
27+
disabled: false
28+
}
29+
}
30+
},
31+
{
32+
id: 'node3',
33+
label: 'Text Node',
34+
children: []
35+
}
36+
];

docs/demo/slots.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
layout: demo
3+
---
4+
5+
## Slots Demo
6+
7+
This page demonstrates slotted content. [See the data used](./slots.js).
8+
9+
{% raw %}
10+
<div id="app">
11+
<tree id="customtree" :model="model">
12+
13+
<template v-slot:text="{ model, customClasses }">
14+
<span>{{ model.label }}. Custom Classes: {{ JSON.stringify(customClasses) }}</span>
15+
</template>
16+
17+
<template v-slot:checkbox="{ model, customClasses, inputId, checkboxChangeHandler }">
18+
<label :for="inputId" :title="model.title">
19+
20+
<input :id="inputId"
21+
type="checkbox"
22+
:disabled="model.state.input.disabled" v-model="model.state.input.value"
23+
@change="checkboxChangeHandler" />
24+
25+
<marquee style="max-width: 6rem">{{ model.label }}. Custom Classes: {{ JSON.stringify(customClasses) }}</marquee>
26+
</label>
27+
</template>
28+
29+
<template v-slot:radio="{ model, customClasses, inputId, inputModel, radioChangeHandler }">
30+
<label :for="inputId" :title="model.title">
31+
32+
<input :id="inputId"
33+
type="radio"
34+
:name="model.input.name"
35+
:value="model.input.value"
36+
:disabled="model.state.input.disabled"
37+
v-model="inputModel"
38+
@change="radioChangeHandler" />
39+
40+
<span style="font-weight: bolder">{{ model.label }}. Custom Classes: {{ JSON.stringify(customClasses) }}</span>
41+
</label>
42+
</template>
43+
44+
</tree>
45+
</div>
46+
{% endraw %}
47+
48+
<script type='module'>
49+
import slotsData from './slots.js';
50+
51+
new Vue({
52+
components: {
53+
tree: window['vue-tree']
54+
},
55+
data() {
56+
return {
57+
model: slotsData
58+
};
59+
}
60+
}).$mount('#app')
61+
</script>

docs/index.md

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Features include:
1414
- Checkboxes
1515
- Radio buttons
1616
- Addition and removal of nodes
17+
- Slots for node content
1718

1819
Planned:
1920

@@ -240,7 +241,9 @@ The display of the treeview can be customized via CSS using the following classe
240241
| `tree-view-node-self-delete-icon` | The `<i>` element containing the delete icon |
241242
| `tree-view-node-children` | The list of child nodes |
242243

243-
## Customizing TreeViewNodes
244+
## Customizing the TreeView
245+
246+
### Customizations Property
244247

245248
It's often helpful to be able to make adjustments to the markup or styles for the tree. You can provide an object to the `modelDefaults.customizations` property of the tree to set a customization affecting all nodes, or to the `customizations` property of a single node. Node-specific customizations will override `modelDefault` customizations.
246249

@@ -266,3 +269,51 @@ A customizations object may have the following properties:
266269
| classes.treeViewNodeSelfDelete | String | Classes to add to the delete button |
267270
| classes.treeViewNodeSelfDeleteIcon | String | Classes to add to the `<i>` element containing the delete icon |
268271
| classes.treeViewNodeChildren | String | Classes to add to the list of child nodes |
272+
273+
### Slots
274+
275+
Sometimes the entire content of a node (_e.g._, the checkbox or text) needs customization beyond what is available through classes. In this case, some slots are available in the TreeView to allow this customization.
276+
277+
| Slot Name | Description | Props |
278+
|:----------|:------------------------------------------------------|:---------------------------------------------------------------------------------------------------|
279+
| text | Replaces the span used for non-input content | model - The TreeViewNode's model |
280+
| | | customClasses - Any custom classes specified in `customizations` |
281+
| checkbox | Replaces the label and content used for checkboxes | model - The TreeViewNode's model |
282+
| | | customClasses - Any custom classes specified in `customizations` |
283+
| | | inputId - The ID for the input (as generated by the TreeViewNode) |
284+
| | | checkboxChangeHandler - The handler for checkbox change events. You should fire this on `change`. |
285+
| radio | Replaces the label and content used for radio buttons | model - The TreeViewNode's model |
286+
| | | customClasses - Any custom classes specified in `customizations` |
287+
| | | inputId - The ID for the input (as generated by the TreeViewNode) |
288+
| | | radioChangeHandler - The handler for radio button change events. You should fire this on `change`. |
289+
290+
Example usage:
291+
292+
```html
293+
<tree-view id="customtree" :model="model">
294+
<template v-slot:text="{ model, customClasses }">
295+
<marquee :title="model.title" <!-- The tree view node's model is available -->
296+
class="tree-view-node-self-text" <!-- Built in classes and overrides are available -->
297+
:class="customClasses.treeViewNodeSelfText">
298+
{{ model.label }}
299+
<marquee>
300+
</template>
301+
302+
<template v-slot:checkbox="{ model, customClasses, inputId, checkboxChangeHandler }">
303+
<label :for="inputId"
304+
:title="model.title"
305+
class="tree-view-node-self-label"
306+
:class="customClasses.treeViewNodeSelfLabel">
307+
308+
<input :id="inputId" <!-- The generated inputId for the node is available -->
309+
class="my-awesome-checkbox-class"
310+
type="checkbox"
311+
:disabled="model.state.input.disabled"
312+
v-model="model.state.input.value"
313+
@change="checkboxChangeHandler" /> <!-- The TreeViewNode change handler is available -->
314+
315+
<blink>{{ "Slotted Content for " + model.label }}</blink>
316+
</label>
317+
</template>
318+
</tree-view>
319+
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "Yet another Vue treeview component.",
44
"author": "Gregg Rapoza <[email protected]>",
55
"license": "MIT",
6-
"version": "0.8.1",
6+
"version": "0.9.0",
77
"browser": "index.js",
88
"repository": {
99
"url": "https://github.com/grapoza/vue-tree",

src/components/TreeView.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414
@treeViewNodeExpandedChange="(t, e)=>$emit('treeViewNodeExpandedChange', t, e)"
1515
@treeViewNodeAdd="(t, p, e)=>$emit('treeViewNodeAdd', t, p, e)"
1616
@treeViewNodeDelete="(t, e)=>$_treeViewNode_handleChildDeletion(t, e)">
17+
18+
<template v-slot:checkbox="{ model, customClasses, inputId, checkboxChangeHandler }">
19+
<slot name="checkbox" :model="model" :customClasses="customClasses" :inputId="inputId" :checkboxChangeHandler="checkboxChangeHandler"></slot>
20+
</template>
21+
<template v-slot:radio="{ model, customClasses, inputId, inputModel, radioChangeHandler }">
22+
<slot name="radio" :model="model" :customClasses="customClasses" :inputId="inputId" :inputModel="inputModel" :radioChangeHandler="radioChangeHandler"></slot>
23+
</template>
24+
<template v-slot:text="{ model, customClasses }">
25+
<slot name="text" :model="model" :customClasses="customClasses"></slot>
26+
</template>
1727
</tree-view-node>
1828
</ul>
1929
</template>

src/components/TreeViewNode.vue

Lines changed: 76 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,72 @@
2626
class="tree-view-node-self-spacer"
2727
:class="customClasses.treeViewNodeSelfSpacer"></span>
2828

29-
<!-- Input and label -->
30-
<label v-if="model.input"
31-
:for="inputId"
32-
:title="model.title"
33-
class="tree-view-node-self-label"
34-
:class="customClasses.treeViewNodeSelfLabel">
35-
36-
<input v-if="model.input.type === 'checkbox'"
37-
:id="inputId"
38-
class="tree-view-node-self-input tree-view-node-self-checkbox"
39-
:class="[customClasses.treeViewNodeSelfInput, customClasses.treeViewNodeSelfCheckbox]"
40-
type="checkbox"
41-
:disabled="model.state.input.disabled"
42-
v-model="model.state.input.value"
43-
@change="$_treeViewNode_onCheckboxChange" />
44-
45-
<input v-if="model.input.type === 'radio'"
46-
:id="inputId"
47-
class="tree-view-node-self-input tree-view-node-self-radio"
48-
:class="[customClasses.treeViewNodeSelfInput, customClasses.treeViewNodeSelfRadio]"
49-
type="radio"
50-
:name="model.input.name"
51-
:value="model.input.value"
52-
:disabled="model.state.input.disabled"
53-
v-model="radioGroupValues[model.input.name]"
54-
@change="$_treeViewNode_onRadioChange" />
55-
56-
{{ model.label }}
57-
</label>
29+
<!-- Inputs and labels -->
30+
<!-- Checkbox -->
31+
<slot v-if="model.input && model.input.type === 'checkbox'"
32+
name="checkbox"
33+
:model="model"
34+
:customClasses="customClasses"
35+
:inputId="inputId"
36+
:checkboxChangeHandler="$_treeViewNode_onCheckboxChange">
37+
38+
<label :for="inputId"
39+
:title="model.title"
40+
class="tree-view-node-self-label"
41+
:class="customClasses.treeViewNodeSelfLabel">
42+
43+
<input :id="inputId"
44+
class="tree-view-node-self-input tree-view-node-self-checkbox"
45+
:class="[customClasses.treeViewNodeSelfInput, customClasses.treeViewNodeSelfCheckbox]"
46+
type="checkbox"
47+
:disabled="model.state.input.disabled"
48+
v-model="model.state.input.value"
49+
@change="$_treeViewNode_onCheckboxChange" />
50+
51+
{{ model.label }}
52+
</label>
53+
</slot>
54+
55+
<!-- Radiobutton -->
56+
<slot v-else-if="model.input && model.input.type === 'radio'"
57+
name="radio"
58+
:model="model"
59+
:customClasses="customClasses"
60+
:inputId="inputId"
61+
:inputModel="radioGroupValues[model.input.name]"
62+
:radioChangeHandler="$_treeViewNode_onRadioChange">
63+
64+
<label :for="inputId"
65+
:title="model.title"
66+
class="tree-view-node-self-label"
67+
:class="customClasses.treeViewNodeSelfLabel">
68+
69+
<input :id="inputId"
70+
class="tree-view-node-self-input tree-view-node-self-radio"
71+
:class="[customClasses.treeViewNodeSelfInput, customClasses.treeViewNodeSelfRadio]"
72+
type="radio"
73+
:name="model.input.name"
74+
:value="model.input.value"
75+
:disabled="model.state.input.disabled"
76+
v-model="radioGroupValues[model.input.name]"
77+
@change="$_treeViewNode_onRadioChange" />
78+
79+
{{ model.label }}
80+
</label>
81+
</slot>
5882

5983
<!-- Text (if not an input) -->
60-
<span v-else
61-
:title="model.title"
62-
class="tree-view-node-self-text"
63-
:class="customClasses.treeViewNodeSelfText">
64-
{{ model.label }}
65-
</span>
84+
<slot v-else
85+
name="text"
86+
:model="model"
87+
:customClasses="customClasses">
88+
89+
<span :title="model.title"
90+
class="tree-view-node-self-text"
91+
:class="customClasses.treeViewNodeSelfText">
92+
{{ model.label }}
93+
</span>
94+
</slot>
6695

6796
<!-- Add Child button -->
6897
<button :id="addChildId"
@@ -107,6 +136,15 @@
107136
@treeViewNodeExpandedChange="(t, e)=>$emit('treeViewNodeExpandedChange', t, e)"
108137
@treeViewNodeAdd="(t, p, e)=>$emit('treeViewNodeAdd', t, p, e)"
109138
@treeViewNodeDelete="(t, e)=>$_treeViewNode_handleChildDeletion(t, e)">
139+
<template v-slot:checkbox="{ model, customClasses, inputId, checkboxChangeHandler }">
140+
<slot name="checkbox" :model="model" :customClasses="customClasses" :inputId="inputId" :checkboxChangeHandler="checkboxChangeHandler"></slot>
141+
</template>
142+
<template v-slot:radio="{ model, customClasses, inputId, inputModel, radioChangeHandler }">
143+
<slot name="radio" :model="model" :customClasses="customClasses" :inputId="inputId" :inputModel="inputModel" :radioChangeHandler="radioChangeHandler"></slot>
144+
</template>
145+
<template v-slot:text="{ model, customClasses }">
146+
<slot name="text" :model="model" :customClasses="customClasses"></slot>
147+
</template>
110148
</TreeViewNode>
111149
</ul>
112150
</li>
@@ -299,13 +337,13 @@
299337
},
300338
$_treeViewNode_onClick(event) {
301339
// Don't fire this if the target is an element which has its own events
302-
if (!event.target.matches("input, .tree-view-node-self-expander, .tree-view-node-self-delete")) {
340+
if (!event.target.matches("input, .tree-view-node-self-expander, .tree-view-node-self-action")) {
303341
this.$emit('treeViewNodeClick', this.model, event);
304342
}
305343
},
306344
$_treeViewNode_onDblclick(event) {
307345
// Don't fire this if the target is an element which has its own events
308-
if (!event.target.matches("input, .tree-view-node-self-expander, .tree-view-node-self-delete")) {
346+
if (!event.target.matches("input, .tree-view-node-self-expander, .tree-view-node-self-action")) {
309347
this.$emit('treeViewNodeDblclick', this.model, event);
310348
}
311349
},
@@ -386,7 +424,7 @@
386424
.tree-view-node-self-checkbox,
387425
.tree-view-node-self-radio,
388426
.tree-view-node-self-spacer,
389-
.tree-view-node-self-delete {
427+
.tree-view-node-self-action {
390428
min-width: 1rem;
391429
}
392430

tests/local/iisexpressstartup.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"C:\Program Files (x86)\IIS Express\iisexpress.exe" /path:D:\Code\JavaScript\vue-tree\

0 commit comments

Comments
 (0)