Created
April 23, 2018 04:54
-
-
Save oskude/bc2b3205051d526820dc918b119c5434 to your computer and use it in GitHub Desktop.
vue.js tree-list form component experiment 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en" dir="ltr"> | |
<head> | |
<meta charset="utf-8"> | |
<title>vue.js tree-list form component experiment 2</title> | |
<script src="vue.js"></script> | |
</head> | |
<body> | |
<div style="display:flex"> | |
<pre style="padding-right:3em"> | |
foo | |
├─ foo-1 | |
│ ├─ foo-1-1 | |
│ └─ foo-1-2 | |
├─ foo-2 | |
│ ├─ foo-2-1 | |
│ └─ foo-2-2 | |
bar | |
├─ bar-1 | |
│ ├─ bar-1-1 | |
│ └─ bar-1-2 | |
└─ bar-2 | |
├─ bar-2-1 | |
└─ bar-2-2 | |
</pre> | |
<pre> | |
1: { id: 1, name: "foo", path: [] }, | |
2: { id: 2, name: "foo-1", path: [1] }, | |
3: { id: 3, name: "foo-1-1", path: [1,2] }, | |
4: { id: 4, name: "foo-1-2", path: [1,2] }, | |
5: { id: 5, name: "foo-2", path: [1] }, | |
6: { id: 6, name: "foo-2-1", path: [1,5] }, | |
7: { id: 7, name: "foo-2-2", path: [1,5] }, | |
8: { id: 8, name: "bar", path: [] }, | |
9: { id: 9, name: "bar-1", path: [8] }, | |
10: { id: 10, name: "bar-1-1", path: [8,9] }, | |
11: { id: 11, name: "bar-1-2", path: [8,9] }, | |
12: { id: 12, name: "bar-2", path: [8] }, | |
13: { id: 13, name: "bar-2-1", path: [8,12] }, | |
14: { id: 14, name: "bar-2-2", path: [8,12] } | |
</pre> | |
</div> | |
<div id="app"> | |
<form method="post"> | |
<fieldset> | |
<legend>example</legend> | |
<tree-list name="cat[]" depth="3" :tree="mytree" :list="mylist"></tree-list> | |
<input type="submit"> | |
</fieldset> | |
</form> | |
</div> | |
</body> | |
<script> | |
Vue.component("tree-list", { | |
props: [ | |
"name", | |
"depth", | |
"tree", | |
"list" | |
], | |
mounted: function () { | |
this.on_list_change(); | |
}, | |
watch: { | |
list: 'on_list_change' | |
}, | |
methods: { | |
on_list_change: function () { | |
console.log("list changed"); | |
// TODO: how do we undisable when none of items children are checked? | |
for (let id of this.list) { | |
for (let parentId of this.tree[id].path) { | |
// TODO: we dont have reference to parent element | |
let parent = document.getElementById(`${this.name}${parentId}`); | |
if (parent) { | |
parent.disabled = true; | |
} else { | |
console.error("no parent found!"); | |
} | |
} | |
} | |
}, | |
to_show_or_not: function (item) { | |
if ( | |
item.path.length == 0 // is root item | |
|| this.list.includes(item.path.slice(-1)[0]) // our parent is shown | |
) { | |
return true; | |
} | |
return false; | |
} | |
}, | |
template: ` | |
<div style="display:flex"> | |
<div v-for="(_, d) in parseInt(depth)"> | |
<template v-for="item in tree"> | |
<tree-list-entry | |
v-if="item.path.length == d" | |
v-show="to_show_or_not(item)" | |
:name="name" | |
:item="item" | |
:list="list" | |
></tree-list-entry> | |
</template> | |
</div> | |
</div> | |
`.replace(/\n/g, "").replace(/>\s*</g, "><") | |
/* above removes those pesky whitespaces. TODO might break something... */ | |
}); | |
Vue.component("tree-list-entry", { | |
props: [ | |
"name", | |
"item", | |
"list" | |
], | |
methods: { | |
on_click: function (evt) { | |
let id = parseInt(evt.target.value); | |
let list = this.$parent.list; // TODO: yeah, i dont care... | |
if(list.includes(id)) { | |
list.splice(list.indexOf(id), 1); | |
} else { | |
list.push(id); | |
} | |
} | |
}, | |
computed: { | |
element_id: function () { | |
return `${this.name}${this.item.id}`; | |
} | |
}, | |
template: ` | |
<div> | |
<label :for="element_id">{{ item.name }}</label> | |
<input | |
type="checkbox" | |
:id="element_id" | |
:name="name" | |
:value="item.id" | |
:checked="list.includes(item.id)" | |
@click="on_click" | |
/> | |
</div> | |
`.replace(/\n/g, "").replace(/>\s*</g, "><") | |
/* above removes those pesky whitespaces. TODO might break something... */ | |
}); | |
/* ignore me, just an example tree list */ | |
var cats = {}; | |
var c = 1; | |
["foo", "bar"].forEach((name)=>{ | |
let path = []; | |
cats[c] = { | |
id: c, | |
name: name, | |
path: Array.from(path) | |
}; | |
path.push(c); | |
c++; | |
for (let x = 1; x <= 2; x++) { | |
cats[c] = { | |
id: c, | |
name: `${name}-${x}`, | |
path: Array.from(path) | |
}; | |
path.push(c); | |
c++; | |
for (let y = 1; y <= 2; y++) { | |
cats[c] = { | |
id: c, | |
name: `${name}-${x}-${y}`, | |
path: Array.from(path) | |
}; | |
c++; | |
} | |
path.splice(path.indexOf(c), 1); | |
} | |
}); | |
var app = new Vue({ | |
el: '#app', | |
data: { | |
mylist: [1,2,3], | |
mytree: cats | |
} | |
}); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment