mdbootstrap / TW-Elements

𝙃𝙪𝙜𝙚 collection of Tailwind MIT licensed (free) components, sections and templates 😎
https://tw-elements.com
MIT License
12.86k stars 1.62k forks source link

[Form Input Custom Classes] [data-te-class-notch-leading-valid, middle and trailing not working in Nuxt 3] #2313

Closed noelc10 closed 7 months ago

noelc10 commented 7 months ago

Describe the bug I try to follow the docs regarding applying a custom class when the field is in valid state with vee-validate, yum and implementing custom validation with those said packages. But it seems that it doesn't override the default valid classes on the input field/s.

To Reproduce Steps to reproduce the behavior:

  1. Copying the login form component from docs
  2. Applying validation with vee-validate and yum, then integrate my way to create custom validation
  3. Since I want to apply the normal state of the field when the value is valid, I try to implement the data-te-class-notch-leading, middle, and trailing-valid attributes to input wrapper
  4. When I try it to Edge browser(Incognito), I test the fields for valid inputs but it doesn't override the default valid TW classes

Expected behavior It should be able to override the input valid state when validation is passed with data-te-class-notch-leading-valid, data-te-class-notch-middle-valid, and data-te-class-notch-trailing-valid.

Actual behavior It doesn't override the default input valid state classes from tw-elements.

Show your code

<script setup>
import { onMounted } from 'vue'
import { useForm } from 'vee-validate';
import * as yup from 'yup';

const emit = defineEmits(['login', 'clearLoginError'])
const props = defineProps({
  formErrors: {
    type: Object,
    default: null
  }
})
const { meta, errors, handleSubmit, defineField } = useForm({
  validationSchema: yup.object({
    email: yup.string().email().required(),
    password: yup.string().min(6).required(),
  })
})
const [email, emailAttrs] = defineField('email');
const [password, passwordAttrs] = defineField('password');
const onSubmit = handleSubmit(values => {
  console.log('onSubmit')
  emit('login', JSON.parse(values))
})

function handleClearError(field) {
  emit('clearLoginError', field)
}

onMounted(async () => {
  const {
    Input,
    Ripple,
    Validation,
    initTE,
  } = await import('tw-elements')

  initTE({ Input, Ripple, Validation }, { allowReinits: true })
})
</script>

<template>
  <form
    data-te-validation-init
    data-te-active-validation="false"
    :data-te-validated="meta.valid || !!props.value?.formErrors"
    @submit.prevent="onSubmit"
  >
    <div
      class="relative mb-6"
      data-te-input-wrapper-init
      data-te-class-notch-leading-valid="border-[#e5e5e5] dark:border-[#e5e5e5] group-data-[te-input-focused]:shadow-[-1px_0_0_#e5e5e5,_0_1px_0_0_#e5e5e5,_0_-1px_0_0_#e5e5e5] group-data-[te-input-focused]:border-[#e5e5e5]"
      data-te-class-notch-middle-valid="border-[#e5e5e5] dark:border-[#e5e5e5] group-data-[te-input-focused]:shadow-[0_1px_0_0_#e5e5e5] group-data-[te-input-focused]:border-[#e5e5e5]"
      data-te-class-notch-trailing-valid="border-[#e5e5e5] dark:border-[#e5e5e5] group-data-[te-input-focused]:shadow-[1px_0_0_#e5e5e5,_0_-1px_0_0_#e5e5e5,_0_1px_0_0_#e5e5e5] group-data-[te-input-focused]:border-[#e5e5e5]"
      data-te-validate="input"
      data-te-valid-feedback="&nbsp;"
      :data-te-invalid-feedback="errors?.email || props.value?.formErrors?.email"
      :data-te-validation-state="errors?.email || props.value?.formErrors?.email ? 'invalid' : 'valid'"
    >
      <input
        v-model="email"
        v-bind="emailAttrs"
        type="text"
        class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[2.15] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
        name="email"
        placeholder="Email Address"
        @input.once="handleClearError('email')"
      />
      <label
        for="email"
        class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[2.15] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[1.15rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[1.15rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
      >
        Email Address
      </label>
    </div>

    <div class="relative mb-6"
      data-te-input-wrapper-init
      data-te-validate="input"
      data-te-valid-feedback="&nbsp;"
      data-te-class-notch-leading-valid="border-[#e5e5e5] dark:border-[#e5e5e5] group-data-[te-input-focused]:shadow-[-1px_0_0_#e5e5e5,_0_1px_0_0_#e5e5e5,_0_-1px_0_0_#e5e5e5] group-data-[te-input-focused]:border-[#e5e5e5]"
      data-te-class-notch-middle-valid="border-[#e5e5e5] dark:border-[#e5e5e5] group-data-[te-input-focused]:shadow-[0_1px_0_0_#e5e5e5] group-data-[te-input-focused]:border-[#e5e5e5]"
      data-te-class-notch-trailing-valid="border-[#e5e5e5] dark:border-[#e5e5e5] group-data-[te-input-focused]:shadow-[1px_0_0_#e5e5e5,_0_-1px_0_0_#e5e5e5,_0_1px_0_0_#e5e5e5] group-data-[te-input-focused]:border-[#e5e5e5]"
      :data-te-invalid-feedback="errors?.password || props.value?.formErrors?.password"
      :data-te-validation-state="errors?.password || props.value?.formErrors?.password ? 'invalid' : 'valid'"
    >
      <input
        v-model="password"
        v-bind="passwordAttrs"
        type="password"
        class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[2.15] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
        name="password"
        placeholder="Password"
        @input.once="handleClearError('password')"
      />
      <label
        for="password"
        class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[2.15] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[1.15rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[1.15rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
      >
        Password
      </label>
    </div>

    <button
      type="submit"
      class="inline-block w-full rounded bg-primary px-7 pb-2.5 pt-3 text-sm font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
      data-te-submit-btn-ref
      :class="!meta.valid || !!props.value?.formErrors ? 'pointer-events-none disabled:opacity-70' : ''"
      :disabled="!meta.valid || !!props.value?.formErrors"
    >
      Log in {{ meta.valid }} {{ !!props.value?.formErrors }} {{ !meta.valid && !!props.value?.formErrors }}
    </button>
  </form>
</template>

Desktop (please complete the following information):

Hoping for the response, help and guidance for this since it is one of the great UI Kit I use since Vuetify.

Thanks.

iprzybysz commented 7 months ago

Hi @noelc10, remove data-te-class attributes from input wrappers and add them to the form element. Then it should change your valid styles correctly.

noelc10 commented 7 months ago

@iprzybysz thank you so much for your response. I appreciate it a lot. It looks like it's working now, hopefully they update the docs about how to properly implement these attributes so that a new user like me will be guided and most of the users will find it friendly when skimming on the docs.

Thank you so much 🙇