Можно ли как нибудь сделать реактивное обновление и отображение данных и отображение данных в зависимости от условий полученных после извлечения этих данных из локального хранилища динамически?
Я тут попытался это сделать - получился небольшой франкенштейн из 2 параметров.
<template>
<div class="accordion">
<div v-if="!item.parent_id" class="box">
<button class="node-tree-button px-0" v-on:click="addNode()">
<div class="">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
</svg>
</div>
<div class="node-tree-button-add-text p-1 px-3">
Добавить корневую папку
</div>
</button>
<div class="how-to p-1">
<router-link to="/how-to-node">
Как перемещать создавать и редактировать папки
</router-link>
</div>
</div>
<div ref="accordion-item" :id="'kt_accordion_'+item.id" v-if="item && item.name && item.parent_id" class="accordion-item">
<h2 class="accordion-header" :id="'kt_accordion_'+item.id+'_header_'+item.id" @mouseover="isHovering = true"
@mouseout="isHovering = false" >
<div class="node-item-wrapper notice d-flex bg-light-primary rounded border p-2" type="button"
v-on:click="folderClick(item.id)"
:data-bs-target="'#kt_accordion_'+item.id+'_body_'+item.id">
<svg class="add-to-folder" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
</svg>
<div class="min-w-10px">
<div style="width: 24px" v-if="item.children && item.children.length > 0" v-on:click="toggleChildren()">
<span class="svg-icon svg-icon-primary svg-icon-2x">
<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" version="1.1">
</svg>
</span>
</div>
</div>
<div ref="div"
class="node-tree-folder-name p-1"
:style="{display: showEditInput ? 'none' : 'block'}"
:id="'node_item_'+item.id+'_input'">
{{ item.name }}
</div>
<input type="text" ref="input" :style="{display: showEditInput ? 'block' : 'none'}"
@keydown.enter="saveNode">
<div class="pl-1">
<svg v-on:click="addNode()" :style="{visibility: isHovering ? 'visible' : 'hidden'}" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
</svg>
</div>
<div class="pl-1">
<svg v-on:click="editNode()" :style="{visibility: isHovering ? 'visible' : 'hidden'}" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
</svg>
</div>
<div class="pl-1">
<svg v-on:click="deleteNode()" :style="{visibility: isHovering ? 'visible' : 'hidden'}" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
</svg>
</div>
</div>
</h2>
</div>
<template v-for="(newItem, index) of item.children">
<div :style="{display: showChildrenFlag ? 'block' : 'none'}" :id="'kt_accordion_'+item.id+'_body_'+item.id"
class="accordion-collapse collapse show"
aria-labelledby="kt_accordion_1_header_1"
:data-bs-parent="'#kt_accordion_'+item.id">
<div class="node-tree-child">
<node-tree ref="node-tree-item-child" :item="newItem" :index="index" :name="newItem.name" @change-value="changeValue">
</node-tree>
</div>
</div>
</template>
</div>
</template>
<script>
import ApiService from "@/core/services/ApiService";
import {useAuthStore} from "@/stores/auth";
export default {
name: "NodeTree",
props: [
'item',
'index',
],
emits: ['update:name'],
components: {
'child': this
},
init() {
},
methods: {
isVisible() {
},
async addNode() {
const api = ApiService;
const auth = useAuthStore();
let openId = null;
await api.post('/category-tree/add', {
user_id: auth.user.id,
id: this.item.id,
name: 'Новая папка',
}).then((response) => {
if (!this.item.children) {
this.item.children = [];
}
this.item.children.push({
id: response.data.id,
name: response.data.name,
parent_id: response.data.parent_id
});
openId = response.data.id;
});
this.showChildren(openId);
},
async saveNode(event) {
await this.$emit('change-value', {
value: event.target.value,
id: this.item.id
});
this.showEditInput = false;
},
async updateNode(object) {
const api = ApiService;
const auth = useAuthStore();
await api.post('/category-tree/edit', {
user_id: auth.user.id,
id: object.id,
name: object.name,
}).then((response) => {
if (!this.item.children) {
this.item.children = [];
}
const item = this.item.children.find(element => element.id === response.data.id);
item.name = response.data.name;
});
},
async editNode() {
if (this.showEditInput === true) {
await this.$emit('change-value', {
value: this.$refs.input.value,
id: this.item.id
});
this.showEditInput = !this.showEditInput;
return;
}
this.$refs.input.value = this.item.name;
this.showEditInput = !this.showEditInput;
setTimeout(() => {
this.$refs.input.focus();
}, 1);
this.emitter.emit("reload-tree");
},
async deleteNode() {
if (confirm('Удалить папку')) {
await this.$parent.deleteChildren(this.index);
}
},
async changeValue(data) {
await this.updateNode({
name: data.value,
id: data.id
});
let element = this.item.children.find(element => element.id === data.id);
element.name = data.value;
},
async deleteChildren(id) {
const api = ApiService;
await api.post('/category-tree/delete', {
id: this.item.children[id].id,
}).then((response) => {
let item = this.item.children.filter(function(item, index) {
return index !== id
});
this.item.children = item;
});
},
showChildren(id = null) {
this.showChildrenFlag = true;
if (id) {
const nodeItem = this.$refs["node-tree-item-child"].find((nodeItem) => {
return nodeItem.item.id === id;
});
nodeItem.editNode();
}
},
hideChildren() {
this.showChildrenFlag = false;
},
toggleChildren() {
this.showChildrenFlag = !this.showChildrenFlag;
},
folderClick(id) {
this.emitter.emit("pick-folder", id);
}
},
data() {
return {
showEditInput: false,
isHovering: false,
showChildrenFlagProperty: true,
task_categories: []
}
},
computed: {
showChildrenFlag: {
get: function () {
return this.showChildrenFlagProperty
},
set: function (value) {
if (this.item) {
localStorage.setItem('node-item-' + this.item.id, value);
this.showChildrenFlagProperty = Boolean(value);
}
},
}
},
mounted() {
if (this.item.parent_id == null) {
this.showChildrenFlagProperty = true;
} else {
if (localStorage.getItem('node-item-' + this.item.id) === 'false') {
this.showChildrenFlagProperty = false;
this.showChildrenFlag = false;
} else {
this.showChildrenFlagProperty = true;
this.showChildrenFlag = true;
}
}
},
};
</script>
<style>
</style>
Здесь самая главная загвоздка в том что тут используются 2 параметра - showChildrenFlagProperty и showChildrenFlag.