removeValuesForNonExistingOrDisabledOptions.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import type {
  3. ObjectSelectOption,
  4. ObjectSelectValue,
  5. } from '#shared/entities/object-attributes/form/resolver/fields/select.ts'
  6. import type { FormKitFrameworkContext, FormKitNode } from '@formkit/core'
  7. import type { Dictionary } from 'ts-essentials'
  8. type OptionValueLookup = Dictionary<ObjectSelectOption>
  9. type SelectValueWithoutBoolean = Exclude<ObjectSelectValue, boolean>
  10. const removeValuesForNonExistingOrDisabledOptions = (node: FormKitNode) => {
  11. const handleNewInputValue = (
  12. payload: SelectValueWithoutBoolean | SelectValueWithoutBoolean[],
  13. context: FormKitFrameworkContext,
  14. ) => {
  15. const optionValueLookup = context.optionValueLookup as OptionValueLookup
  16. if (Array.isArray(payload)) {
  17. // TODO: Workaround for empty string, because currently the "nulloption" exists also for multiselect fields (#4513).
  18. const availableValues = payload.filter(
  19. (selectValue: string | number) =>
  20. (typeof optionValueLookup[selectValue] !== 'undefined' &&
  21. !optionValueLookup[selectValue].disabled) ||
  22. selectValue === '',
  23. )
  24. return availableValues
  25. }
  26. if (
  27. typeof optionValueLookup[payload] === 'undefined' ||
  28. optionValueLookup[payload].disabled
  29. ) {
  30. if (typeof optionValueLookup[node.props._init] === 'undefined') {
  31. const getPreselectValue =
  32. context.getPreselectValue as () => ObjectSelectValue
  33. return context.clearable || getPreselectValue === undefined
  34. ? undefined
  35. : getPreselectValue()
  36. }
  37. return node.props._init
  38. }
  39. return payload
  40. }
  41. node.on('created', () => {
  42. const { context } = node
  43. if (!context) return
  44. node.at('$root')?.settled.then(() => {
  45. node.hook.input((payload, next) => {
  46. if (!context.fns.hasValue(payload) || !context.optionValueLookup)
  47. return next(payload)
  48. return next(handleNewInputValue(payload, context))
  49. })
  50. })
  51. })
  52. }
  53. export default removeValuesForNonExistingOrDisabledOptions