Thanks for your insight. It helped me solve the issue.
I was not able to get an option working using computed
but I was with watch
.
The updated index.js:
window.panel.plugin('myNamespace/parentChildSelect', {
fields: {
parentChildSelect: {
props: {
categoryPages: Array,
label: String,
help: String,
value: Object,
},
data() {
return {
items: this.categoryPages && JSON.parse(this.categoryPages),
selection: this.blankSelection(),
}
},
mounted() {
// If there's a draft, any existing categories will have already been parsed from JSON into a JS object.
// Accordingly, we need to handle loading them as either.
var maybeExistingSelection = this.value
if (maybeExistingSelection) {
this.selection =
typeof maybeExistingSelection === 'object'
? maybeExistingSelection
: JSON.parse(maybeExistingSelection)
}
},
methods: {
blankSelection() {
return {
parents: [],
children: [],
}
},
select(selectionPath, value) {
this.selection[selectionPath].push(value)
},
unselect(selectionPath, value) {
this.selection[selectionPath] = this.selection[selectionPath].filter((i) => i !== value)
},
handleClick(selectionPath, value) {
if (this.selection[selectionPath].includes(value)) {
// Unselect the clicked item
this.unselect(selectionPath, value)
// If unselecting a parent, also ensure all children are unselected.
if (selectionPath === 'parents') {
if (this.items[value].children) {
Object.keys(this.items[value].children).forEach((childKey) => {
this.unselect('children', childKey)
})
}
}
} else {
// Select the clicked item.
this.select(selectionPath, value)
// If it's a child, ensure that the parent is selected.
if (selectionPath === 'children') {
var parent = value.substring(value.lastIndexOf('/'), 0)
if (!this.selection.parents.includes(parent)) {
this.select('parents', parent)
}
}
}
// This effectively tells Kirby that a change has been made that needs to be saved or discarded.
// Without this no changes on the field are ever saved.
this.$emit('input', this.selection)
},
},
watch: {
value(newValue) {
if (newValue) {
this.selection = typeof newValue === 'object' ? newValue : JSON.parse(newValue)
} else {
this.selection = this.blankSelection()
}
},
},
template: /* html */ `
<div>
<k-headline class="_mb075">
{{ label }}
<span
v-if="selection.parents.length + selection.children.length"
class="_c-light"
>
({{ selection.parents.length + selection.children.length }})
</span>
</k-headline>
<div class="parentChildSelect-container">
<div
class="parentChildSelect-parentChildWrapper"
v-for="(parentValue, parentKey) in items"
>
<button
type="button"
class="parentChildSelect-entry parentChildSelect-entryParent"
v-bind:class="{ 'parentChildSelect-entrySelected': selection.parents.includes(parentKey) }"
@click="handleClick('parents', parentKey)"
>
<span class="parentChildSelect-checkbox"></span>
{{ parentValue.title }}
</button>
<div v-if="parentValue.children">
<button
type="button"
class="parentChildSelect-entry parentChildSelect-entryChild"
v-bind:class="{ 'parentChildSelect-entrySelected': selection.children.includes(childKey) }"
@click="handleClick('children', childKey)"
v-for="(childValue, childKey) in parentValue.children"
>
<span class="parentChildSelect-checkbox"></span>
{{ childValue.title }}
</button>
</div>
</div>
</div>
<div
v-if="help"
class="_mt075 _fs-14 _c-light"
v-html="help"
>
</div>
</div>
`,
},
},
})