Closed starker-xp closed 8 months ago
Select interfaces render the items array at the point when you click it. If you want a global select source, you can define a constant at a module level and modify it as needed. If each node instance needs their own array, you can make a class based node that manages its own item array.
export class TestSelect extends AbstractNode {
inputs: Record<string, NodeInterface<any>> = {};
outputs: Record<string, NodeInterface<any>> = {};
calculate?: CalculateFunction<any, any, CalculationContext<any, IEngine<any>>> | undefined;
type: string = "TestSelect";
items: string[];
get title() { return "Test Select"; }
constructor() {
super();
this.items = ["1"];
}
public onPlaced(): void {
this.addOutput("addItem",new ButtonInterface("Add Select Item",()=>{
this.items.push((this.items.length+1).toString()) ;
}));
this.addOutput("dynamicSelect",new SelectInterface("Select","1", this.items));
}
}
It would also be nice if SelectInterface could optionally accept a function that returns an array but currently, it requires an array instance.
I took the problem in a different direction.
I used the @vueform/multiselect
package
import { type ComponentOptions, markRaw } from "vue";
import { NodeInterface } from "@baklavajs/core";
import MultiSelectInterfaceComponent from "./MultiSelectInterface.vue";
export class MultiSelectInterface<V = string> extends NodeInterface<V> {
component = markRaw(MultiSelectInterfaceComponent) as ComponentOptions;
baseUri: string;
constructor(name: string, value: V, baseUri: string) {
super(name, value);
this.baseUri = baseUri;
}
}
export { MultiSelectInterfaceComponent };
<script setup lang="ts">
import Multiselect from "@vueform/multiselect";
import { ref, watch, toValue } from "vue";
import type { MultiSelectInterface } from "./MultiSelectInterface";
const props = defineProps<{
intf: MultiSelectInterface<unknown>;
}>();
const valued = ref(props.intf.value);
const el = ref<HTMLElement | null>(null);
watch(valued, () => {
props.intf.value = toValue(valued);
});
const fetchLanguages = async (query) => {
// From: https://www.back4app.com/database/paul-datasets/list-of-all-programming-languages/get-started/javascript/rest-api/fetch?objectClassSlug=dataset
let where = "";
if (query) {
where =
"&where=" +
encodeURIComponent(
JSON.stringify({
ProgrammingLanguage: {
$regex: `${query}|${query.toUpperCase()}|${query[0].toUpperCase() + query.slice(1)}`,
},
}),
);
}
const response = await fetch(
"https://parseapi.back4app.com/classes/All_Programming_Languages?limit=9999&order=ProgrammingLanguage&keys=ProgrammingLanguage" +
where,
{
headers: {
"X-Parse-Application-Id": "XpRShKqJcxlqE5EQKs4bmSkozac44osKifZvLXCL", // This is the fake app's application id
"X-Parse-Master-Key": "Mr2UIBiCImScFbbCLndBv8qPRUKwBAq27plwXVuv", // This is the fake app's readonly master key
},
},
);
const data = await response.json(); // Here you have the data that you need
return data.results.map((item) => {
return { value: item.ProgrammingLanguage, label: item.ProgrammingLanguage };
});
};
</script>
<template>
<div>
<label class="typo__label" for="ajax">Choose a programming language</label>
<Multiselect
ref="el"
v-model="valued"
:options="
async (query) => {
return await fetchLanguages(query);
}
"
:filter-results="false"
:resolve-on-load="false"
:delay="0"
:searchable="true"
:object="true"
/>
</div>
</template>
<style src="@vueform/multiselect/themes/default.css"></style>
<style>
.character-label-icon {
margin: 0 6px 0 0;
height: 26px;
}
.multiselect {
color: black;
}
</style>
This is just a draft. I'll fix 2-3 problems and make a PR.
Hello, I'm looking to create a scenario editor for an RPG. I'm potentially going to end up with a lot of choices for building quests. So I'm looking for a way to fill in the SelectInterface dynamically. Or at least a way to update them.