UNPKG

@zenweb/form

Version:

Zenweb Form module

131 lines (130 loc) 3.6 kB
import { $enum } from 'ts-enum-util'; import { Field, simple } from '../field.js'; import { typeCast } from 'typecasts'; class BaseSelect extends Field { _choices = []; /** * 设置选择项 */ choices(choices) { for (const c of choices) { if (typeof c === 'object') { this._choices.push(c); } else { this._choices.push({ label: String(c), value: c }); } } return this; } /** * 设置选择项,使用指定的 value 和 label */ choicesMap(choices, valueKey, labelKey) { return this.choices(choices.map(i => ({ value: i[valueKey], label: i[labelKey] }))); } /** * 设置选项,使用对象的 key 和 value */ choicesObject(obj) { return this.choices(Object.entries(obj).map(([value, label]) => ({ value: typeCast(value, { type: this._valueType }), label, }))); } /** * 使用 ts 的 enum 类型作为选择项 */ choicesEnum(enumObj) { return this.choices($enum(enumObj).map((value, label) => ({ value, label }))); } /** * 是否没有设置选择项 */ isEmpty() { return this._choices.length === 0; } /** * 检查选择项是否已经设置 */ assertEmpty() { if (this.isEmpty()) { this.fail('form.select.options.empty'); } } extra() { return { choices: this._choices, }; } } export class Select extends BaseSelect { clean(data) { data = super.clean(data); if (data === undefined) return; this.assertEmpty(); const item = this._choices.find(i => i.value == data); if (item) { if (item.disabled) { this.fail('form.select.choice-disabled', { data, label: item.label }); } return data; } this.fail('form.select.choice-invalid', { data }); } } export class Radio extends Select { } export class Multiple extends BaseSelect { _max; _min; /** 最多可以选择数量 */ max(v) { this._max = v; return this; } /** 最少选择数量 */ min(v) { this._min = v; return this; } extra() { return Object.assign(super.extra(), { max: this._max, min: this._min, }); } clean(data) { data = super.clean(data); if (data === undefined) return; this.assertEmpty(); data = Array.isArray(data) ? data : [data]; const max = Math.min(this._max || Number.MAX_VALUE, this._choices.length); if (data.length > max) { this.fail('form.select.choice-max', { max }); } if (this._min && data.length < this._min) { this.fail('form.select.choice-min', { min: this._min }); } for (const i of data) { const item = this._choices.find(c => c.value == i); if (item) { if (item.disabled) { this.fail('form.select.choice-disabled', { data: i, label: item.label }); } } else { this.fail('form.select.choice-invalid', { data: i }); } } return data; } } export class Checkbox extends Multiple { } export const select = simple(Select); export const radio = simple(Radio); export const multiple = simple(Multiple); export const checkbox = simple(Checkbox);