Mini-ghost/vorms

custom events naming for support ionic

reslear opened this issue · 5 comments

Describe the feature

for example

<ion-input
  label="Alphanumeric Characters"
  :value="inputModel"
  @ionInput="onInput($event)"
  ref="ionInputEl"
></ion-input>

https://ionicframework.com/docs/api/input#events

I understand that you can make a custom element - but I would like to use ionic components in a more basic way without loss of native ionic types.

Additional information

  • Would you be willing to help implement this feature?

current workaround solutions (like mapper) is:

<script lang="ts">
function toIonicAttrs(attrs: ComputedRef<FieldAttrs>) {
  return {
    name: attrs.value?.name,
    onIonInput: attrs.value?.onInput,
    onIonBlur: attrs.value?.onBlur,
    onIonChange: attrs.value?.onChange,
  }
}

const { value: clientAnalytics, attrs } = register('clientAnalytics')
const clientAnalyticsAttrs = computed(() => toIonicAttrs(attrs))
</script>

<template>
  <ion-input
    v-bind="clientAnalyticsAttrs"
    v-model="clientAnalytics"
    :class="{
      'ion-touched': !!touched.clientAnalytics,
      'ion-valid': !errors.clientAnalytics,
      'ion-invalid': !!errors.clientAnalytics,
    }"
    :error-text="errors.clientAnalytics"
  ></ion-input>
</template>

workaround solutions v2:

diff --git a/dist/index.d.ts b/dist/index.d.ts
index c8556747207135d5efa4b18380e83a66b2bc198f..231a8b26ee5eb5d603b864c3193813fb6c4a1ca0 100644
--- a/dist/index.d.ts
+++ b/dist/index.d.ts
@@ -108,6 +108,7 @@ interface UseFormOptions<Values extends FormValues> {
     onSubmit: (values: Values, helper: FormSubmitHelper<Values>) => void | Promise<any>;
     onInvalid?: (errors: FormErrors<Values>) => void;
     validate?: (values: Values) => void | object | Promise<FormErrors<Values>>;
+    customAttrsNames: Partial<Record<keyof FieldAttrs, string>>
 }
 /**
  * Custom composition API to mange the entire form.
diff --git a/dist/index.esm.mjs b/dist/index.esm.mjs
index e6f542b531d33ab9c4529be3f5a8efdc9249c9d5..4b1f50a1f90b00e98d3eb8b0c716f253e928237d 100644
--- a/dist/index.esm.mjs
+++ b/dist/index.esm.mjs
@@ -443,10 +443,12 @@ const emptyTouched = {};
  * ```
  */
 function useForm(options) {
-    const { validateOnMounted = false, validateMode = 'submit', reValidateMode = 'change', onSubmit, onInvalid, } = options;
+    const { validateOnMounted = false, validateMode = 'submit', reValidateMode = 'change', onSubmit, onInvalid, customAttrsNames = {} } = options;
     let initialValues = klona(options.initialValues);
     let initialErrors = klona(options.initialErrors || emptyErrors);
     let initialTouched = klona(options.initialTouched || emptyTouched);
+    const attrsNames = Object.assign({ name: 'name', onBlur: 'onBlur', onChange: 'onChange', onInput: 'onInput' }, customAttrsNames)
+    
     const [state, dispatch] = useFormStore(reducer, {
         values: reactive(klona(initialValues)),
         errors: ref(klona(initialErrors)),
@@ -582,10 +584,10 @@ function useForm(options) {
     };
     const getFieldAttrs = (name) => {
         return computed(() => ({
-            name: unref(name),
-            onBlur: handleBlur,
-            onChange: handleChange,
-            onInput: handleInput,
+            [attrsNames.name]: unref(name),
+            [attrsNames.onBlur]: handleBlur,
+            [attrsNames.onChange]: handleChange,
+            [attrsNames.onInput]: handleInput,
         }));
     };
     const getFieldError = (name) => {
<script lang="ts">
const { 
  register,
  // ...
} = useForm({
  // ...
  customAttrsNames: {
    onChange: 'onIonChange',
    onInput: 'onIonInput',
    onBlur: 'onIonBlur',
  },
})

const { value: clientAnalytics, attrs: clientAnalyticsAttrs } = register('clientAnalytics')
</script>

<template>
  <ion-input
    v-bind="clientAnalyticsAttrs"
    v-model="clientAnalytics"
    :class="{
      'ion-touched': !!touched.clientAnalytics,
      'ion-valid': !errors.clientAnalytics,
      'ion-invalid': !!errors.clientAnalytics,
    }"
    :error-text="errors.clientAnalytics"
  ></ion-input>
</template>

I was also thinking of adding this as a global value but there are cases where we use native events, so the ideal solution is probably to move the functionality to register, like:

// concept 
const { attrs } = register('clientAnalytics', {
  attrs: { 
    // map custom attrs 
  }
})

There is also an idea to add custom properties:

// concept 
const { attrs } = register('clientAnalytics', {
  attrsAdittional: computed(() => ({ 
    class: {
      'ion-touched': !!touched.clientAnalytics,
      'ion-valid': !errors.clientAnalytics,
      'ion-invalid': !!errors.clientAnalytics,
    },
    'error-text': errors.clientAnalytics
  }))
})

As a result, we get :

<ion-input
  v-bind="clientAnalyticsAttrs"
  v-model="clientAnalytics"
></ion-input>

😱

Well, I've found a more or less solution:

<script lang="ts">
const toIonicAttrs = (attrs: FieldAttrs) => ({
  name: attrs?.name,
  onIonInput: attrs?.onInput,
  onIonBlur: attrs?.onBlur,
  onIonChange: attrs?.onChange,
})

const { value: clientAnalytics, attrs: clientAnalyticsAttrs } = register('clientAnalytics')
</script>

<template>
  <ion-input
    v-bind="toIonicAttrs(clientAnalyticsAttrs)"
    v-model="clientAnalytics"
    :class="{
      'ion-touched': !!touched.clientAnalytics,
      'ion-valid': !errors.clientAnalytics,
      'ion-invalid': !!errors.clientAnalytics,
    }"
    :error-text="errors.clientAnalytics"
  ></ion-input>
</template>