CheckBoxGroup.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <slot />
  3. </template>
  4. <script setup lang="ts">
  5. import { onMounted, onUpdated, provide, toRef, type Ref } from 'vue';
  6. import { ArrayUtils } from '@imengyu/imengyu-utils';
  7. import { useFieldChildValueInjector } from './FormContext';
  8. export interface CheckBoxGroupProps {
  9. /**
  10. * 当前复选框组选中的项目
  11. */
  12. modelValue?: string[];
  13. /**
  14. * 是否禁用整组复选框,设置后会禁用全部复选框。
  15. * @default false
  16. */
  17. disabled?: boolean;
  18. /**
  19. * 是否支持多选。仅限制用户选择,通过代码设置值时,不受到此限制。
  20. * @default true
  21. */
  22. multiple?: boolean;
  23. }
  24. export interface CheckBoxGroupInterface {
  25. /**
  26. * 切换所有复选框
  27. * @param options 传 true 为选中,false 为取消选中,不传参为取反
  28. */
  29. toggleAll: (options?: boolean | undefined | CheckBoxGroupToggleOptions) => void;
  30. }
  31. export interface CheckBoxGroupToggleOptions {
  32. /**
  33. * 是否是选中
  34. * @required true
  35. */
  36. checked: boolean,
  37. /**
  38. * 是否跳过禁用的复选框
  39. * @required true
  40. */
  41. skipDisabled: boolean,
  42. }
  43. export interface CheckBoxGroupContextInfo {
  44. value: Ref<string[]>,
  45. disabled: Ref<boolean>,
  46. onValueChange: (name: string|undefined, v: boolean) => void;
  47. onAddItem: (name: string, disabled: boolean) => void;
  48. }
  49. const props = withDefaults(defineProps<CheckBoxGroupProps>(), {
  50. modelValue: () => [] ,
  51. disabled: false,
  52. multiple: true,
  53. });
  54. const {
  55. value,
  56. updateValue,
  57. } = useFieldChildValueInjector(
  58. toRef(props, 'modelValue'),
  59. (v) => emit('update:modelValue', v)
  60. );
  61. provide<CheckBoxGroupContextInfo>('checkBoxGroupContext', {
  62. value: value,
  63. disabled: toRef(props, 'disabled'),
  64. onValueChange,
  65. onAddItem: (name, disabled) => {
  66. allCheck.set(name, disabled);
  67. },
  68. });
  69. const emit = defineEmits([ 'update:modelValue' ]);
  70. const allCheck = new Map<string, boolean>();
  71. function onValueChange(name: string|undefined, checked: boolean) {
  72. if (checked && !props.multiple) {
  73. updateValue([name as string]);
  74. return;
  75. }
  76. const valueNew = (value.value || []).concat();
  77. if (checked)
  78. ArrayUtils.addOnce(valueNew, name as string);
  79. else
  80. ArrayUtils.remove(valueNew, name as string);
  81. updateValue(valueNew);
  82. }
  83. function toggleAll(options?: boolean|undefined|CheckBoxGroupToggleOptions) {
  84. const allCheckNames = Array.from(allCheck.keys());
  85. if (typeof options === 'undefined') {
  86. //反选
  87. const valueNew = allCheckNames.filter((i) => value ? !value.value.includes(i) : false);
  88. updateValue(valueNew);
  89. } else if (typeof options === 'boolean') {
  90. //选中/取消选中
  91. const valueNew = options === true ? allCheckNames.concat() : [];
  92. updateValue(valueNew);
  93. } else if (typeof options === 'object') {
  94. //根据参数,选择时跳过禁用的选项
  95. const valueNew = allCheckNames.filter((name) => {
  96. if (options.skipDisabled && allCheck.get(name))
  97. return value ? value.value.includes(name) : false;
  98. return options.checked;
  99. });
  100. updateValue(valueNew);
  101. }
  102. }
  103. defineOptions({
  104. options: {
  105. styleIsolation: "shared",
  106. virtualHost: true,
  107. }
  108. })
  109. defineExpose<CheckBoxGroupInterface>({
  110. toggleAll,
  111. })
  112. </script>