feat: chip closable advance
jingyuexing opened this issue · comments
When I used the Closable feature of the Chip component in an actual project, I found that there were many limitations, such as being unable to delete or add items freely. Therefore, I wrote an enhanced version of the useSelection hook. Since I only tested it in my own project, I cannot predict how it will work in your project. Please modify it according to your specific situation.
export function useSelectionAdavance<Item, Multi extends boolean, Closable extends boolean, InitialValue extends Item>(
params: Params<Item, Multi, Closable, InitialValue>
): ReturnValue<Item, Multi> {
const { items, multi = false, initialValue = undefined, closable = false } = params;
const _items = toRef(items);
const _multi = toRef(multi);
const _initialValue = toRef(initialValue);
const _val = ref(
// _initialValue.value,
// (_items.value as Item[]).find(i => {
// // ℹ️ If initial value is object compare using `JSON.stringify` else just use `===`
// return (isObject(_initialValue.value) && isObject(i))
// ? JSON.stringify(_initialValue.value) === JSON.stringify(i)
// : _initialValue.value === i
// }),
(_items.value as Item[]).find(i => isEqual(_initialValue.value, i))
) as ReturnValue<Item, Multi>["value"];
const select = (option: Item) => {
// If multiple selection is enabled
if (_multi.value) {
// If value is not set (Means previously multi was false) => Initialize new set and assign it to value
if (!Array.isArray(_val.value)) {
_val.value = [option] as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
} else {
// Else toggle option in array
const index = _val.value.indexOf(option);
if (index === -1) _val.value.push(option);
else _val.value.splice(index, 1);
}
} else {
_val.value = option as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
}
};
const close = (option:Item) => {
if (_multi.value && Array.isArray(_items.value)) {
const index = _items.value.indexOf(option);
if (index !== -1) _items.value.splice(index, 1);
} else {
_val.value = undefined as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
}
}
const append = (val:Item)=>{
if (_multi.value && Array.isArray(_items.value)) {
_items.value.push(val);
}
}
watch(_multi, val => {
_val.value = (val ? [] : undefined) as UnwrapRef<ReturnValue<Item, Multi>["value"]>;
});
const _options = computed(() => _items.value.map(item => ({
value: item,
isSelected: _multi.value
? Array.isArray(_val.value) ? _val.value.includes(item) : false
: isEqual(item, _val.value),
isClosed:false
}))) as ReturnValue<Item, Multi>['options']
return {
value: _val,
select,
close,
append,
options: _options
};
}
Two new hooks have been added: close, which removes an element from the items array, and append, which adds an element to the items array.
I wonder what if we update the passed array while using useSelection
:
const items = ref(['apple', 'banana', 'orange', 'watermelon'])
const { options, select, value } = useSelection({
items: items,
multi: isMultiEnabled,
})
setTimeout(() => {
items.value.push('mango')
}, 2000);
Can you please give it a try and let know if above works?
I wonder what if we update the passed array while using
useSelection
:const items = ref(['apple', 'banana', 'orange', 'watermelon']) const { options, select, value } = useSelection({ items: items, multi: isMultiEnabled, }) setTimeout(() => { items.value.push('mango') }, 2000);Can you please give it a try and let know if above works?
I'm not sure if you are showing me another way to achieve the same goal. As for the above code, there's no problem and it can run as expected.