Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The prop 'hasError' generates a TS error, types that are generated based on the docs are incorrect #11510

Closed
ghost opened this issue Nov 28, 2021 · 6 comments · Fixed by #14243
Assignees
Labels
area/typescript bug/2-confirmed We have reproduce the problem and confirmed that this is a bug. kind/bug 🐞 Qv2 🔝 Quasar v2 issues

Comments

@ghost
Copy link

ghost commented Nov 28, 2021

First of all I deeply apologize for my bad English. I wanted to use the internal validation from quasar and my code is below this text also what I've learned is from the docs here :
https://quasar.dev/vue-components/input#example--form-validation
But The prop 'hasError' (that is used for internal validation on inputRef and it gives 'true' if the inputs has error) generates a TS error that says Property 'hasError' does not exist on type QInput and I guess there is a problem with the types that are generated based on the docs.

As you can see in the simple code below, I have to use a // @ts-expect-error because the code inuputRef.value?.hasError generates an error and it also gives me what I wanted for validations at the same time.
the TS error says : Property 'hasError' does not exist on type QInput
but the code is correct and the property 'hasError' does exist on type QInput and it's just the TS types that are generated based on the docs and they are incorrect I guess.

Thanks in advance 🙏

My example code that shows the problem but first remove the // @ts-expect-error from it :

<template>
  <q-page class="flex flex-center" padding>
    <form @submit.prevent.stop="onSubmit">
      <q-card class="full-width" style="max-width: 350px">
        <q-card-section class="bg-primary text-white">
          <div class="text-h6">login</div>
          <div class="text-subtitle2">
           subtext
          </div>
        </q-card-section>

        <q-separator />

        <q-card-actions vertical>
          <q-input
            ref="usernameRef"
            v-model="username"
            standout="bg-teal text-white"
            label="username"
            class="q-my-md"
            hint="this is username"
            lazy-rules
            :rules="usernameRules"
          >
            <template #prepend>
              <q-icon name="fingerprint" />
            </template>
          </q-input>

          <q-input
            ref="passwordRef"
            v-model="password"
            standout="bg-teal text-white"
            label="password"
            class="q-mb-md"
            hint="this is password"
            :type="isPwd ? 'password' : 'text'"
            lazy-rules
            :rules="passwordRules"
          >
            <template #prepend>
              <q-icon name="password" />
            </template>
            <template #append>
              <q-icon
                :name="isPwd ? 'visibility_off' : 'visibility'"
                class="cursor-pointer"
                @click="isPwd = !isPwd"
              />
            </template>
          </q-input>

          <q-btn
            color="secondary"
            icon="login"
            label="login"
            class="q-mb-sm"
            @click="onSubmit"
          />
        </q-card-actions>
      </q-card>
    </form>
  </q-page>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';
import { useQuasar, QInput } from 'quasar';

export default defineComponent({
  name: 'Login',
  setup() {
    const $q = useQuasar();

    const username = ref<string>('');
    const usernameRef = ref<QInput | null>(null);

    const usernameRules = [
      (value: string) =>
        (value !== null && value !== '') ||
        'username cant be null',
    ];

    const password = ref<string>('');
    const passwordRef = ref<QInput | null>(null);

    const passwordRules = [
      (value: string) =>
        (value !== null && value !== '') || 'password cant be null',
    ];

    const isPwd = ref<boolean>(true);

    function onSubmit(): void {
      usernameRef.value?.validate();
      passwordRef.value?.validate();

      // @ts-expect-error     I have to temporary use a (ts-expect-error). Using the prop 'hasError' generates a ts error but it's correct and the docs are incorrect in this point it seems, and there is a problem with the types that are generated based on the docs I guess.
      if (usernameRef.value?.hasError || passwordRef.value?.hasError) {
        $q.notify({
          icon: 'warning',
          color: 'negative',
          message: 'please fix the errors first the press it again',
        });
      } else {
        $q.notify({
          icon: 'done',
          color: 'positive',
          message: 'succeed',
        });
      }
    }

    return {
      username,
      usernameRef,
      usernameRules,
      password,
      passwordRef,
      passwordRules,
      isPwd,
      onSubmit,
    };
  },
});
</script>
@ghost ghost added kind/docs 📄 Qv2 🔝 Quasar v2 issues labels Nov 28, 2021
@yusufkandemir
Copy link
Member

You can use the return values of validate() calls instead of hasError.

And the best way to approach this use case is instead of a regular form, using QForm. That way, you can call validate on the q-form ref, and it will give you the validation result of the whole form. So, instead of dealing with all the input refs, calling validate on them, etc. you can have a single place where you manage them all.

But, let's say you had a proper case that definitely needed to access hasError. We are not generating types for dynamically exposed instance properties like this, we are only generating types for instance methods. So, it's expected in some way. However, we need to find out how many instance properties we currently have, how they are structured, are they meant to be used publicly in the first place, etc. Then depending on the result take an action, which may result in updating the examples in our documentation, or adding a new type of top-level prop to JSON API schema, which would then be used to generate the TS types, and also get shown on API viewer sections on the docs on a new tab.

@ghost
Copy link
Author

ghost commented Nov 29, 2021

Hey @yusufkandemir Thank you so much for the comment, your guide and the information will help me for sure... Thanks a lot! 🙏
And with all respect ; I wanted to say that in fact the only thing we have from a software is just a documentation.
There is nothing in the documentation other than hasError in order to know if a input has error or not.
I respectfully invite you to read this part of the documentation https://quasar.dev/vue-components/input#example--form-validation that is using hasError for the example.

Then for me it seemed there are no other ways because I'm just starting with quasar and I'm just reading the docs! also when I brought up my problem inside the quasar discord server, the only person that replied to me, told me that hasError is correct but it's only about the ts types.

The prop that should work is 'hasError' but the docs are incorrect in this point it seems, and the types are generated based on the docs. So use hasError and do a comment // @ts-expect-error above that line.

With what I said I also mention that I'm really newbie and I'm just a document reader with no background about what really happens behind the scene for now, so I hope I'm not wrong about this issue? If I'm wrong let me know please because with what you said

We are not generating types for dynamically exposed instance properties like this, we are only generating types for instance methods

I have to close the issue.

I'm so grateful for the response, your hard works and efforts to make the quasar and it's community better.
Thanks in advance! 🙏 and Have a great time ahead! 🌹

@yusufkandemir
Copy link
Member

Thanks for the kind comment, I appreciate it. I totally understand you and agree that this is confusing.

Generally, if something is confusing like this, it might end up being a private thing accidentally used somewhere, or just got overlooked with less to no documentation at all. hasError example is 3 years old, so it might be both. So, that's why I said we have to evaluate it first. Then, if we consider hasError is something really needed, and we have other dynamic properties for other components as well, we will update the documentation to make them clearer, and they will also be in the API card, just like props, methods, events, etc.

So, I didn't close the issue because we will evaluate this, and you don't have to close it.

@rstoenescu
Copy link
Member

rstoenescu commented Jan 7, 2022

hasError is still needed @yusufkandemir

@squareloop1
Copy link

squareloop1 commented Jan 22, 2022

To chime in on this: Sometimes you don't want to use validate() to check if the input has any validation errors as this would trigger the validation again even if it happened before and you don't want to fire it again. hasError provides a way to check for validation errors without triggering validation itself which is very useful and needed in some cases. The current error prop is not filled while hasError is correctly filled, despite docs saying both fields should theoretically behave the same.

@rstoenescu
Copy link
Member

Fix will be available in Quasar v2.8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/typescript bug/2-confirmed We have reproduce the problem and confirmed that this is a bug. kind/bug 🐞 Qv2 🔝 Quasar v2 issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants