primevue-mirror/components/lib/organizationchart/OrganizationChartNode.vue

186 lines
6.7 KiB
Vue
Raw Normal View History

2022-09-06 12:03:37 +00:00
<template>
<table :class="cx('table')" v-bind="ptm('table')">
2023-05-10 08:07:14 +00:00
<tbody v-bind="ptm('body')">
<tr v-if="node" v-bind="ptm('row')">
<td :colspan="colspan" v-bind="ptm('cell')">
<div :class="cx('node')" @click="onNodeClick" v-bind="getPTOptions('node')">
2022-09-14 11:26:01 +00:00
<component :is="templates[node.type] || templates['default']" :node="node" />
<a v-if="toggleable" tabindex="0" :class="cx('nodeToggler')" @click="toggleNode" @keydown="onKeydown" v-bind="getPTOptions('nodeToggler')">
<component v-if="templates.togglericon" :is="templates.togglericon" :expanded="expanded" class="p-node-toggler-icon" />
<component v-else :is="expanded ? 'ChevronDownIcon' : 'ChevronUpIcon'" :class="cx('nodeTogglerIcon')" v-bind="getPTOptions('nodeTogglerIcon')" />
2022-09-06 12:03:37 +00:00
</a>
</div>
</td>
</tr>
<tr :style="childStyle" :class="cx('lines')" v-bind="ptm('lines')">
2022-09-06 12:03:37 +00:00
<td :colspan="colspan">
<div :class="cx('lineDown')" v-bind="ptm('lineDown')"></div>
2022-09-06 12:03:37 +00:00
</td>
</tr>
<tr :style="childStyle" :class="cx('lines')" v-bind="ptm('lines')">
2022-09-06 12:03:37 +00:00
<template v-if="node.children && node.children.length === 1">
2023-05-10 08:07:14 +00:00
<td :colspan="colspan" v-bind="ptm('lineCell')">
<div :class="cx('lineDown')" v-bind="ptm('lineDown')"></div>
2022-09-06 12:03:37 +00:00
</td>
</template>
<template v-if="node.children && node.children.length > 1">
2022-09-14 11:26:01 +00:00
<template v-for="(child, i) of node.children" :key="child.key">
<td
:class="
cx('lineLeft', {
context: {
i
}
})
"
v-bind="getNodeOptions(!(i === 0), 'lineLeft')"
>
&nbsp;
</td>
<td
:class="
cx('lineRight', {
context: {
i
}
})
"
v-bind="getNodeOptions(!(i === node.children.length - 1), 'lineRight')"
>
&nbsp;
</td>
2022-09-06 12:03:37 +00:00
</template>
</template>
</tr>
<tr :style="childStyle" :class="cx('nodes')" v-bind="ptm('nodes')">
2023-05-10 08:07:14 +00:00
<td v-for="child of node.children" :key="child.key" colspan="2" v-bind="ptm('nodeCell')">
2022-09-14 11:26:01 +00:00
<OrganizationChartNode
:node="child"
:templates="templates"
:collapsedKeys="collapsedKeys"
@node-toggle="onChildNodeToggle"
:collapsible="collapsible"
:selectionMode="selectionMode"
:selectionKeys="selectionKeys"
@node-click="onChildNodeClick"
2023-05-10 08:07:14 +00:00
:pt="pt"
:unstyled="unstyled"
2022-09-14 11:26:01 +00:00
/>
2022-09-06 12:03:37 +00:00
</td>
</tr>
</tbody>
</table>
</template>
<script>
2023-05-10 08:07:14 +00:00
import BaseComponent from 'primevue/basecomponent';
import ChevronDownIcon from 'primevue/icons/chevrondown';
import ChevronUpIcon from 'primevue/icons/chevronup';
2022-09-14 11:26:01 +00:00
import { DomHandler } from 'primevue/utils';
2022-09-06 12:03:37 +00:00
export default {
name: 'OrganizationChartNode',
2023-05-10 08:07:14 +00:00
extends: BaseComponent,
2022-09-06 12:03:37 +00:00
emits: ['node-click', 'node-toggle'],
props: {
node: {
type: null,
default: null
},
templates: {
type: null,
default: null
},
collapsible: {
type: Boolean,
default: false
},
collapsedKeys: {
type: null,
default: null
},
selectionKeys: {
type: null,
default: null
},
selectionMode: {
type: String,
default: null
}
},
methods: {
2023-05-10 08:07:14 +00:00
getPTOptions(key) {
return this.ptm(key, {
context: {
expanded: this.expanded,
selectable: this.selectable,
selected: this.selected,
toggleable: this.toggleable,
active: this.selected
}
});
},
getNodeOptions(lineTop, key) {
return this.ptm(key, {
context: {
lineTop
}
});
},
2022-09-06 12:03:37 +00:00
onNodeClick(event) {
if (DomHandler.getAttribute(event.target, 'nodeToggler') || DomHandler.getAttribute(event.target, 'nodeTogglerIcon')) {
2022-09-06 12:03:37 +00:00
return;
}
if (this.selectionMode) {
this.$emit('node-click', this.node);
}
},
onChildNodeClick(node) {
this.$emit('node-click', node);
},
toggleNode() {
this.$emit('node-toggle', this.node);
},
onChildNodeToggle(node) {
this.$emit('node-toggle', node);
2022-12-08 11:04:25 +00:00
},
onKeydown(event) {
if (event.code === 'Enter' || event.code === 'Space') {
this.toggleNode();
event.preventDefault();
}
2022-09-06 12:03:37 +00:00
}
},
computed: {
leaf() {
return this.node.leaf === false ? false : !(this.node.children && this.node.children.length);
},
colspan() {
2022-09-14 11:26:01 +00:00
return this.node.children && this.node.children.length ? this.node.children.length * 2 : null;
2022-09-06 12:03:37 +00:00
},
childStyle() {
return {
visibility: !this.leaf && this.expanded ? 'inherit' : 'hidden'
2022-09-14 11:26:01 +00:00
};
2022-09-06 12:03:37 +00:00
},
expanded() {
return this.collapsedKeys[this.node.key] === undefined;
},
selectable() {
return this.selectionMode && this.node.selectable !== false;
},
selected() {
return this.selectable && this.selectionKeys && this.selectionKeys[this.node.key] === true;
},
toggleable() {
return this.collapsible && this.node.collapsible !== false && !this.leaf;
}
},
components: {
ChevronDownIcon: ChevronDownIcon,
ChevronUpIcon: ChevronUpIcon
2022-09-06 12:03:37 +00:00
}
2022-09-14 11:26:01 +00:00
};
2022-09-06 12:03:37 +00:00
</script>