Reputation: 23
I'm using tomselect with vuejs3 and I realized that when I use more than one tomselect in the same component and use the dropdown_close and item_remove events, the tomselect that was not used stops working these events, so I can't capture the moment of the user's action and perform a new report query and make it more dynamic for user navigation, how can I resolve this situation?
<template>
<TomSelect
v-model="filtroEmpPedido"
class="w-full"
refKey="tomSelectEmpPedido"
id="tomSelectEmpPedido"
multiple
:options="{
plugins: {
remove_button: {
title: 'Remover',
},
clear_button: {
title: 'Remover Todos',
},
},
}"
>
<option v-for="item in empresapedido" :key="item" :value="item.cd_emppedido">
{{ item.ds_empresa }}
</option>
</TomSelect>
</template>
<script setup>
const tomSelectTransp = ref();
provide('bind[tomSelectTransp]', (el) => {
tomSelectTransp.value = el;
});
const tomSelectEmpPedido = ref();
provide('bind[tomSelectEmpPedido]', (el) => {
tomSelectEmpPedido.value = el;
});
onMounted(async () => {
tomSelectTransp.value.TomSelect.on('dropdown_close', () => {
rastreio();
});
tomSelectTransp.value.TomSelect.on('item_remove', () => {
rastreio();
});
tomSelectEmpPedido.value.TomSelect.on('dropdown_close', () => {
rastreio();
});
tomSelectEmpPedido.value.TomSelect.on('item_remove', () => {
rastreio();
});
});
</script>
Component TomSelect
Main.vue
<template>
<select
v-select-directive="{ props, emit, computedOptions }"
class="tom-select"
>
<slot></slot>
</select>
</template>
<script setup>
import { computed, watch, toRaw, ref, onMounted, inject } from "vue";
import { setValue, init, updateValue } from "./index";
import dom from "@left4code/tw-starter/dist/js/dom";
const vSelectDirective = {
mounted(el, { value }) {
// Clone the select element to prevent tom select remove the original element
const clonedEl = dom(el).clone().insertAfter(el)[0];
dom(el).attr("hidden", true);
// Initialize tom select
setValue(clonedEl, value.props);
init(el, clonedEl, value.props, value.emit, value.computedOptions);
// Attach instance
tomSelectRef.value = clonedEl;
},
updated(el, { value }) {
const clonedEl = dom(el).next()[0];
const modelValue = toRaw(value.props.modelValue);
updateValue(
el,
clonedEl,
modelValue,
value.props,
value.emit,
value.computedOptions
);
// Attach instance
tomSelectRef.value = clonedEl;
},
};
const props = defineProps({
options: {
type: Object,
default() {
return {};
},
},
modelValue: {
type: [String, Number, Array],
default: "",
},
refKey: {
type: String,
default: null,
},
});
const emit = defineEmits();
const tomSelectRef = ref();
const bindInstance = () => {
if (props.refKey) {
const bind = inject(`bind[${props.refKey}]`);
if (bind) {
bind(tomSelectRef.value);
}
}
};
// Compute all default options
const computedOptions = computed(() => {
let options = {
...props.options,
plugins: {
dropdown_input: {},
...props.options.plugins,
},
};
if (Array.isArray(props.modelValue)) {
options = {
persist: false,
create: true,
onDelete: function (values) {
return confirm(
values.length > 1
? "Are you sure you want to remove these " +
values.length +
" items?"
: 'Are you sure you want to remove "' + values[0] + '"?'
);
},
...options,
plugins: {
remove_button: {
title: "Remove this item",
},
...options.plugins,
},
};
}
return options;
});
// Watch value change
watch(
computed(() => props.modelValue),
() => {
emit("change");
}
);
onMounted(() => {
bindInstance();
});
</script>
index.js
import dom from "@left4code/tw-starter/dist/js/dom";
import TomSelect from "tom-select";
import _, { clone } from "lodash";
const setValue = (el, props) => {
if (props.modelValue.length) {
dom(el).val(props.modelValue);
}
};
const init = (originalEl, clonedEl, props, emit, computedOptions) => {
// On option add
if (Array.isArray(props.modelValue)) {
computedOptions = {
onOptionAdd: function (value) {
// Add new option
const newOption = document.createElement("option");
newOption.value = value;
newOption.text = value;
originalEl.add(newOption);
// Emit option add
emit("optionAdd", value);
},
...computedOptions,
};
}
clonedEl.TomSelect = new TomSelect(clonedEl, computedOptions);
// On change
clonedEl.TomSelect.on("change", function (selectedItems) {
emit(
"update:modelValue",
Array.isArray(selectedItems) ? [...selectedItems] : selectedItems
);
});
};
const getOptions = (options, tempOptions = []) => {
options.each(function (optionKey, optionEl) {
if (optionEl instanceof HTMLOptGroupElement) {
getOptions(dom(optionEl).children(), tempOptions);
} else {
tempOptions.push(optionEl);
}
});
return tempOptions;
};
const updateValue = (
originalEl,
clonedEl,
modelValue,
props,
emit,
computedOptions
) => {
// Remove old options
for (const [optionKey, option] of Object.entries(
clonedEl.TomSelect.options
)) {
if (
!getOptions(dom(clonedEl).prev().children()).filter((optionEl) => {
return optionEl.value === option.value;
}).length
) {
clonedEl.TomSelect.removeOption(option.value);
}
}
// Update border style
dom(clonedEl.TomSelect.wrapper).css(
"border-color",
dom(originalEl).css("border-color")
);
// Add new options
dom(clonedEl)
.prev()
.children()
.each(function () {
clonedEl.TomSelect.addOption({
text: dom(this).text(),
value: dom(this).attr("value"),
});
});
// Refresh options
clonedEl.TomSelect.refreshOptions(false);
// Update value
if (
(!Array.isArray(modelValue) &&
modelValue !== clonedEl.TomSelect.getValue()) ||
(Array.isArray(modelValue) &&
!_.isEqual(modelValue, clonedEl.TomSelect.getValue()))
) {
clonedEl.TomSelect.destroy();
dom(clonedEl).html(dom(clonedEl).prev().html());
setValue(clonedEl, props);
init(originalEl, clonedEl, props, emit, computedOptions);
}
};
export { setValue, init, updateValue };
Upvotes: 1
Views: 404