Skip to content

Commit 0e892a2

Browse files
authored
Merge pull request #128 from grapoza/add-child-prop-names
Adds childrenPropNames to the model
2 parents cc9876d + c829011 commit 0e892a2

11 files changed

+107
-17
lines changed

docsrc/index.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,17 @@ To see it in action, try out the [demos](demos.html).
100100

101101
## Tree Props
102102

103-
| Prop | Type | Description | Default value | Required |
104-
|:-----------------|:---------|:----------------------------------------------------------------------------------------------|:----------------------------------|:---------|
105-
| initialModel | Array | The data model containing [model data](#model-data) | - | Yes |
106-
| customAriaKeyMap | Object | An object, the properties of which are arrays to keyCodes for various actions | See [Aria](#setting-key-bindings) | |
107-
| idPropNames | Array | An array of property names which will be searched (in order) on each node to use as its ID | `['id']` | |
108-
| labelPropNames | Array | An array of property names which will be searched (in order) on each node to use as its label | `['label']` | |
109-
| modelDefaults | Object | An object containing defaults for all nodes that do not specify the given properties | `{}` | |
110-
| radioGroupValues | Object | An object, the properties of which correspond to radio button group selections | `{}` | |
111-
| selectionMode | String | How selection should operate (see [Selection Mode](#selection-mode)) | `null` (cannot select nodes) | |
112-
| skinClass | String | A class name to apply to the tree that specifies a skin to use (see [Skins](#skins)) | `"default-tree-view-skin"` | |
103+
| Prop | Type | Description | Default value | Required |
104+
|:------------------|:---------|:---------------------------------------------------------------------------------------------------|:----------------------------------|:---------|
105+
| initialModel | Array | The data model containing [model data](#model-data) | - | Yes |
106+
| childrenPropNames | Array | An array of property names which will be searched (in order) on each node to use as its child list | `['children']` | |
107+
| customAriaKeyMap | Object | An object, the properties of which are arrays to keyCodes for various actions | See [Aria](#setting-key-bindings) | |
108+
| idPropNames | Array | An array of property names which will be searched (in order) on each node to use as its ID | `['id']` | |
109+
| labelPropNames | Array | An array of property names which will be searched (in order) on each node to use as its label | `['label']` | |
110+
| modelDefaults | Object | An object containing defaults for all nodes that do not specify the given properties | `{}` | |
111+
| radioGroupValues | Object | An object, the properties of which correspond to radio button group selections | `{}` | |
112+
| selectionMode | String | How selection should operate (see [Selection Mode](#selection-mode)) | `null` (cannot select nodes) | |
113+
| skinClass | String | A class name to apply to the tree that specifies a skin to use (see [Skins](#skins)) | `"default-tree-view-skin"` | |
113114

114115
## Selection Mode
115116

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 <grapoza@gmail.com>",
55
"license": "MIT",
6-
"version": "1.2.1",
6+
"version": "1.3.0",
77
"browser": "index.js",
88
"repository": {
99
"url": "https://github.com/grapoza/vue-tree",

src/components/TreeView.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<tree-view-node v-for="(nodeModel) in model"
77
:key="nodeModel.id"
88
:aria-key-map="ariaKeyMap"
9+
:children-prop-names="childrenPropNames"
910
:depth="0"
1011
:model-defaults="modelDefaults"
1112
:id-prop-names="idPropNames"
@@ -54,6 +55,14 @@
5455
TreeViewNode,
5556
},
5657
props: {
58+
childrenPropNames: {
59+
type: Array,
60+
required: false,
61+
default: function () { return ["children"]; },
62+
validator: function (value) {
63+
return value.length > 0 && value.every(e => typeof e === 'string');
64+
}
65+
},
5766
idPropNames: {
5867
type: Array,
5968
required: false,

src/components/TreeViewNode.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,9 @@
141141
:class="customClasses.treeViewNodeChildren"
142142
role="group"
143143
:aria-hidden="(!model.state.expanded).toString()">
144-
<TreeViewNode v-for="nodeModel in model.children"
144+
<TreeViewNode v-for="nodeModel in model[childrenPropName]"
145145
:key="nodeModel[$_treeViewNode_getIdPropNameForNode(nodeModel)]"
146+
:children-prop-names="childrenPropNames"
146147
:depth="depth + 1"
147148
:id-prop-names="idPropNames"
148149
:initial-model="nodeModel"
@@ -190,6 +191,10 @@
190191
TreeViewNodeAria
191192
],
192193
props: {
194+
childrenPropNames: {
195+
type: Array,
196+
required: true
197+
},
193198
depth: {
194199
type: Number,
195200
required: true
@@ -263,6 +268,9 @@
263268
canExpand() {
264269
return this.model.children.length > 0 && this.model.expandable;
265270
},
271+
childrenPropName() {
272+
return this.childrenPropNames.find(pn => Array.isArray(this.model[pn]));
273+
},
266274
customClasses() {
267275
return (this.model.customizations || {}).classes || {};
268276
},
@@ -377,7 +385,7 @@
377385
this.$set(input, 'name', 'unspecifiedRadioName');
378386
}
379387
if (typeof input.value !== 'string' || input.value.trim().length === 0) {
380-
this.$set(input, 'value', this.model[labelPropName].replace(/[\s&<>"'\/]/g, ''));
388+
this.$set(input, 'value', this.model[this.labelPropName].replace(/[\s&<>"'\/]/g, ''));
381389
}
382390
if (!this.radioGroupValues.hasOwnProperty(input.name)) {
383391
this.$set(this.radioGroupValues, input.name, '');

tests/unit/TreeView.eventHandling.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function createWrapper(customPropsData, customAttrs) {
1919
});
2020
}
2121

22-
describe('TreeView.vue', () => {
22+
describe('TreeView.vue (event handling)', () => {
2323

2424
let wrapper = null;
2525

tests/unit/TreeView.spec.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,15 @@ describe('TreeView.vue', () => {
204204
expect(wrapper.vm.labelPropNames).to.eql(['label']);
205205
});
206206
});
207+
208+
describe('when childrenPropNames is not specified', () => {
209+
210+
beforeEach(() => {
211+
wrapper = createWrapper();
212+
});
213+
214+
it('has a default value of ["children"]', () => {
215+
expect(wrapper.vm.childrenPropNames).to.eql(['children']);
216+
});
217+
});
207218
});

tests/unit/TreeViewAria.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ describe('TreeView.vue (ARIA)', () => {
324324

325325
beforeEach(async () => {
326326
wrapper = createWrapper({ initialModel: generateNodes(['Ecsf', ['ecS', 'ecs'], 'ecs'], {}), selectionMode: 'single' });
327-
wrapper.setProps({ selectionMode: 'selectionFollowsFocus' })
327+
wrapper.setProps({ selectionMode: 'selectionFollowsFocus' });
328328
//wrapper.vm.selectionMode = 'selectionFollowsFocus';
329329
await wrapper.vm.$nextTick();
330330
});

tests/unit/TreeViewNode.customizations.spec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const getDefaultPropsData = function () {
2020
insertItem: [45], // Insert
2121
deleteItem: [46] // Delete
2222
},
23+
childrenPropNames: ['children'],
2324
idPropNames: ['id'],
2425
initialModel: generateNodes(['ces'], radioState)[0],
2526
labelPropNames: ['label'],
@@ -79,6 +80,7 @@ describe('TreeViewNode.vue (customizations)', () => {
7980

8081
wrapper = createWrapper({
8182
ariaKeyMap: {},
83+
childrenPropNames: ['children'],
8284
idPropNames: ['id'],
8385
initialModel,
8486
labelPropNames: ['label'],
@@ -199,6 +201,7 @@ describe('TreeViewNode.vue (customizations)', () => {
199201
wrapper = createWrapper(
200202
{
201203
ariaKeyMap: {},
204+
childrenPropNames: ['children'],
202205
idPropNames: ['id'],
203206
initialModel,
204207
labelPropNames: ['label'],
@@ -237,6 +240,7 @@ describe('TreeViewNode.vue (customizations)', () => {
237240
wrapper = createWrapper(
238241
{
239242
ariaKeyMap: {},
243+
childrenPropNames: ['children'],
240244
idPropNames: ['id'],
241245
initialModel,
242246
labelPropNames: ['label'],
@@ -287,6 +291,7 @@ describe('TreeViewNode.vue (customizations)', () => {
287291
wrapper = createWrapper(
288292
{
289293
ariaKeyMap: {},
294+
childrenPropNames: ['children'],
290295
idPropNames: ['id'],
291296
initialModel,
292297
labelPropNames: ['label'],

tests/unit/TreeViewNode.interactions.spec.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const getDefaultPropsData = function () {
2020
insertItem: [45], // Insert
2121
deleteItem: [46] // Delete
2222
},
23+
childrenPropNames: ['children'],
2324
idPropNames: ['id'],
2425
initialModel: generateNodes(['ces'], radioState)[0],
2526
labelPropNames: ['label'],
@@ -116,6 +117,7 @@ describe('TreeViewNode.vue (interactions)', () => {
116117
let radioState = {};
117118
wrapper = createWrapper({
118119
ariaKeyMap: {},
120+
childrenPropNames: ['children'],
119121
idPropNames: ['id'],
120122
initialModel: generateNodes(['ces', ['ces']], radioState)[0],
121123
labelPropNames: ['label'],
@@ -188,6 +190,7 @@ describe('TreeViewNode.vue (interactions)', () => {
188190
radioState = {};
189191
wrapper = createWrapper({
190192
ariaKeyMap: {},
193+
childrenPropNames: ['children'],
191194
idPropNames: ['id'],
192195
initialModel: generateNodes(['res'], radioState)[0],
193196
labelPropNames: ['label'],
@@ -231,6 +234,7 @@ describe('TreeViewNode.vue (interactions)', () => {
231234
let radioState = {};
232235
wrapper = createWrapper({
233236
ariaKeyMap: {},
237+
childrenPropNames: ['children'],
234238
idPropNames: ['id'],
235239
initialModel: generateNodes(['es', ['ds']], radioState)[0],
236240
labelPropNames: ['label'],
@@ -268,6 +272,7 @@ describe('TreeViewNode.vue (interactions)', () => {
268272

269273
wrapper = createWrapper({
270274
ariaKeyMap: {},
275+
childrenPropNames: ['children'],
271276
idPropNames: ['id'],
272277
initialModel: generateNodes(['esa'], radioState, "", addChildCallback)[0],
273278
labelPropNames: ['label'],
@@ -307,6 +312,7 @@ describe('TreeViewNode.vue (interactions)', () => {
307312

308313
wrapper = createWrapper({
309314
ariaKeyMap: {},
315+
childrenPropNames: ['children'],
310316
idPropNames: ['id'],
311317
initialModel: generateNodes(['esa'], radioState, "", addChildCallback)[0],
312318
labelPropNames: ['label'],

0 commit comments

Comments
 (0)