| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- // components/form-picker/form-picker.ts
- interface Option {
- label: string;
- value: any;
- checked?: boolean;
- disabled?: boolean;
- mutex?: boolean;
- };
- const filtration = (selected: string[] | Set<string>, options: Option[], option?: Option): string[] => {
- const _selected = new Set(selected);
- if (option) {
- if (_selected.has(option.value)) {
- _selected.delete(option.value);
- } else {
- if (option.mutex) {
- _selected.clear();
- } else {
- for (const option of options) {
- if (option.mutex) _selected.delete(option.value);
- }
- }
- _selected.add(option.value);
- }
- }
- return [..._selected];
- }
- const reset = (values: Option[] | Option | string, options: Option[]) => {
- const selected = new Set<string>();
- const _values = Array.isArray(values) ? values : values ? [values] : [];
- for (const item of _values) {
- const value = typeof item === 'object' ? item?.value : item;
- if (value && options.find(item => item.value === value)) selected.add(value);
- }
- for (const option of options) {
- if (option.checked) selected.add(option.value);
- }
- return filtration(selected, options);
- }
- Component({
- options: {
- multipleSlots: true,
- },
- lifetimes: {
- attached() {
- console.log('attached');
- }
- },
- /**
- * 组件的属性列表
- */
- properties: {
- visible: { type: Boolean, value: false },
- title: { type: String, value: '' },
- value: { type: Array, value: [] },
- options: { type: Array, value: [] },
- optionsColumns: { type: Number, value: 1 },
- itemHeight: { type: Number, value: 64 },
- multiple: { type: Boolean, value: true },
- closeOnOverlayClick: { type: Boolean, value: true },
- },
- /**
- * 组件的初始数据
- */
- data: {
- containerHeight: 350,
- gap: 8,
- selected: [] as any[],
- },
- observers: {
- 'options,optionsColumns,itemHeight'(options, columns, height) {
- const rows = Math.ceil(options.length / columns);
- this.setData({ containerHeight: Math.min(rows * height + (rows - 1) * this.data.gap, 350) })
- },
- 'value, options'(values: Option[] | Option | string, options: Option[]) {
- this.setData({ selected: reset(values, options) });
- }
- },
- /**
- * 组件的方法列表
- */
- methods: {
- handle(event: WechatMiniprogram.TouchEvent) {
- const index = event.currentTarget.dataset.index;
- const option = this.data.options[index];
- if (option.disabled) return;
- if (this.data.multiple) {
- this.setData({ selected: filtration(this.data.selected, this.data.options, option) });
- } else {
- this.setData({ selected: this.data.selected.includes(option.value) ? [] : [option.value] });
- }
- },
- onConfirm() {
- const get = (option: Option) => option ? ({ label: option.label, value: option.value }) : null;
- this.setData({ visible: false })
- this.triggerEvent('confirm', {
- selected: this.data.selected,
- options: this.data.selected
- .map(value => get(this.data.options.find(item => item.value === value)))
- .filter(Boolean),
- })
- this.triggerEvent('close', { trigger: 'confirm-btn' });
- },
- onCancel() {
- this.setData({ visible: false });
- this.triggerEvent('cancel');
- this.triggerEvent('close', { trigger: 'cancel-btn' });
- },
- onVisibleChange(event: any) {
- if (!event.detail.visible) {
- this.triggerEvent('close', { trigger: event.detail.trigger })
- setTimeout(() => { this.setData({ selected: reset(this.data.value, this.data.options) }); }, 100)
- };
- }
- }
- })
|