-
Notifications
You must be signed in to change notification settings - Fork 80
/
Copy pathTreeView.vue
145 lines (126 loc) · 3.35 KB
/
TreeView.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<template>
<div class="tree-view-wrapper">
<tree-view-item
class="tree-view-item-root"
:data="parsedData"
:max-depth="allOptions.maxDepth"
:current-depth="0"
:modifiable="allOptions.modifiable"
:link="allOptions.link"
:limit-render-depth="allOptions.limitRenderDepth"
@change-data="onChangeData"/>
</div>
</template>
<script>
import _ from 'lodash';
import TreeViewItem from './TreeViewItem.vue';
export default {
components: {
TreeViewItem
},
name: 'tree-view',
props: ['data', 'options'],
methods: {
// Transformer for the non-Collection types,
// like String, Integer of Float
transformValue(valueToTransform, keyForValue) {
return {
key: keyForValue,
type: 'value',
value: valueToTransform
};
},
// Since we use lodash, the _.map method will work on
// both Objects and Arrays, returning either the Key as
// a string or the Index as an integer
generateChildrenFromCollection(collection) {
return _.map(collection, (value, keyOrIndex) => {
if (this.isObject(value)) {
return this.transformObject(value, keyOrIndex);
}
if (this.isArray(value)) {
return this.transformArray(value, keyOrIndex);
}
if (this.isValue(value)) {
return this.transformValue(value, keyOrIndex);
}
});
},
// Transformer for the Array type
transformArray(arrayToTransform, keyForArray) {
return {
key: keyForArray,
type: 'array',
children: this.generateChildrenFromCollection(arrayToTransform)
};
},
// Transformer for the Object type
transformObject(objectToTransform, keyForObject, isRootObject = false) {
return {
key: keyForObject,
type: 'object',
isRoot: isRootObject,
children: this.generateChildrenFromCollection(objectToTransform)
};
},
// Helper Methods for value type detection
isObject(value) {
return _.isPlainObject(value);
},
isArray(value) {
return _.isArray(value);
},
isValue(value) {
return !this.isObject(value) && !this.isArray(value);
},
onChangeData(path, value) {
const lastKey = _.last(path);
const newPath = _.dropRight(_.drop(path));
const data = _.cloneDeep(this.data);
let targetObject = data;
_.forEach(newPath, key => {
targetObject = targetObject[key];
});
if (targetObject[lastKey] !== value) {
targetObject[lastKey] = value;
this.$emit('change-data', data);
}
}
},
computed: {
allOptions() {
return _.extend({}, {
rootObjectKey: 'root',
maxDepth: 4,
limitRenderDepth: false,
modifiable: false,
link: false
}, (this.options || {}));
},
parsedData() {
// Take the JSON data and transform
// it into the Tree View DSL
// Strings or Integers should not be attempted to be split, so we generate
// a new object with the string/number as the value
if (this.isValue(this.data)) {
return this.transformValue(this.data, this.allOptions.rootObjectKey);
}
// If it's an object or an array, transform as an object
return this.transformObject(this.data, this.allOptions.rootObjectKey, true);
}
}
};
</script>
<style scoped>
.tree-view-wrapper {
overflow: auto;
}
/* Find the first nested node and override the indentation */
.tree-view-item-root > .tree-view-item-leaf > .tree-view-item {
margin-left: 0!important;
}
/* Root node should not be indented */
.tree-view-item-root {
margin-left: 0!important;
}
</style>