Challenges in Transitioning from Vue.js Typescript Options to Composition API

After successfully solving the issue, take a step-by-step look through the question to understand how the problems were fixed.

I recently explored the composition API () and attempted to convert my TypeScript-based existing code from Vue.js Option API. Unfortunately, I couldn't get it to work properly and ended up feeling a bit confused about how the composition API functions.

Below is my working code:

<script lang="ts">
  import Vue from "vue";
  import {inputFields} from "@/mixins/inputField/inputField";
  import VuePersianDatetimePicker from "vue-persian-datetime-picker"
  import {util_timestampz_formatter, util_timestampz_now} from "@/utils/commonUtility";
  import {InputFieldHelper} from "@/mixins/Helpers/FormGeneratorInputFieldHelper/InputField.Helper.mixin";

  export default Vue.extend({
    name: "DateTimePicker",
    props: ['instance', "value", "formSection", "isEnable"],
    components: {
      datePicker: VuePersianDatetimePicker
    },
    data() {
        return {
          inputField: new InputFieldHelper(this.value, this.instance, this.formSection, this.isEnable)
      }
    },
    mounted() {
        //@ts-ignore
        this.instance.min = util_timestampz_now();
    },
    methods: {
      updateValue() {
          let new_data = this.inputField.updateValue();
          new_data ? this.$emit("updateValue", new_data) : "";
      },
      updateDateTime(time: string) {
          //@ts-ignore
          this.inputField.inputValue = util_timestampz_formatter(this.inputField.inputValue);
          //@ts-ignore
          this.updateValue();
      },
    }
  });
</script>

And here is the converted version using the composition API which currently has some issues:

<script lang="ts">
  import Vue from "vue";
  import {reactive, createComponent, onMounted} from "@vue/composition-api";
  import VuePersianDatetimePicker from "vue-persian-datetime-picker"
  import {util_timestampz_formatter, util_timestampz_now} from "@/utils/commonUtility";
  import {InputFieldHelper} from "@/mixins/Helpers/FormGeneratorInputFieldHelper/InputField.Helper.mixin";
  import {FormGeneratorInputField} from "@/types";

  export default createComponent({
    name: "DateTimePicker",
    props: {
      instance,
      value,
      formSection,
      isEnable,
    },
    components: {
      datePicker: VuePersianDatetimePicker
    },
    setup(props, context) {
      const inputField = reactive(new InputFieldHelper(props.value, props.instance, props.formSection, props.isEnable));
      onMounted(() => {
        props.instance.min = util_timestampz_now();
      });
      const updateValue = () => {
        let new_data = inputField.updateValue();
        new_data ? context.$emit("updateValue", new_data) : "";
      };
      const updateDateTime = (time: string) => {
        inputField.inputValue = util_timestampz_formatter(inputField.inputValue);
        updateValue();
      };
      return {
        inputField, updateValue, updateDateTime
      }
    }
  });
</script>

Some errors are being displayed in WebStorm related to the code:

https://i.sstatic.net/H73Q7.png

Is there a way to resolve these errors correctly?

.................

Update 1:

I realized that I made a mistake in handling props (I assumed Vue would automatically handle typescript definitions). Thanks to paleo, the initial problem has been resolved. Furthermore, if you encounter similar type errors for props as shown below: https://i.sstatic.net/OynM7.png

Thanks to , you can pass your created type interface as a function as demonstrated below: https://i.sstatic.net/e6sX7.png

However, there are still some unresolved issues that need to be addressed, such as:

1. When I removed `reactive`, reactivity seems to not function properly, leading to an "unresolved variable or missing import statement" error in the template. https://i.sstatic.net/nicbU.png

..........................

Update 2: Sharing props and utilizing composition functions:

Upon converting from the option-based API to the composition API, I noticed that the latter was more efficient. Special thanks to paleo and Maximilian Shrwa Muller (I highly recommend watching this free video: https://www.youtube.com/watch?v=V-xK3sbc7xI), along with considerable Google search efforts, especially struggling with this link . As a result, I rewrote the code as follows:

<script lang="ts">
  import {createComponent, onMounted} from "@vue/composition-api";
  import VuePersianDatetimePicker from "vue-persian-datetime-picker"
  import {util_timestampz_formatter, util_timestampz_now} from "@/utils/commonUtility";
  import {
    useInputFieldComposition,
    inputFieldProps
  } from "@/mixins/Helpers/FormGeneratorInputFieldHelper/inputField.composition";
  import {ComponentPropsOptions} from "@vue/composition-api/dist/component/componentProps";

  export default createComponent({
    name: "DateTimePicker",
    props: inputFieldProps as ComponentPropsOptions,
    components: {
      datePicker: VuePersianDatetimePicker
    },
    setup(props, context) {
      const {inputField, updateValue} = useInputFieldComposition(props, context);
      onMounted(() => {
        props.instance.min = util_timestampz_now();
      });
      const updateDateTime = (time: string) => {
        inputField.inputValue = util_timestampz_formatter(inputField.inputValue);
        updateValue();
      };
      return {
        inputField, updateValue, updateDateTime
      }
    }
  });
</script>

This approach maintains neatness since everything shared among components resides in another file named `inputField.compositions` as showcased below:

//inputField.composition.ts
import {PropType, reactive} from "@vue/composition-api";
import {FormGeneratorInputField} from "@/types";
import {InputFieldHelper} from "@/mixins/Helpers/FormGeneratorInputFieldHelper/InputField.Helper.mixin";

export const inputFieldProps = {
  instance: {
    type: Object as PropType<FormGeneratorInputField>,
    required: true
  },
  value: {
    type: Object,
    required: true
  },
  formSection: {
    type: String,
    required: true
  },
  isEnable: {
    type: Boolean,
    required: true
  },
};
export const useInputFieldComposition = (props: any, context: any) => {
  let inputField  = reactive(new InputFieldHelper(props.value, props.instance, props.formSection, props.isEnable));
  const updateValue = (): any => {
    let new_data = inputField.passInfoMixedValue();
    new_data ? context.emit("updateValue", new_data) : "";
    return new_data;
  };

  return {
    props, inputField, updateValue
  }

With this feature, TypeScript can be fully utilized for optimal project development.

Lastly, please note that although your project will work perfectly when using the Vue Composition API, WebStorm might display warnings about specific parts of the code in the template, such as unresolved variables. These updates fall under ongoing development, as indicated in this issue: .

Answer №1

Take a look at the guide on props. Here's an example:

    props: {
      instance: {
        type: Object,
        required: true
      },
      value: {
        type: Object,
        required: true
      },
      formSection: {
        type: Object,
        required: true
      },
      isEnable: {
        type: Boolean,
        required: false
      },
    },

If you want to improve types, you can use PropType:

import { PropType } from "@vue/composition-api/dist/component/componentProps";
// …

    props: {
      instance: {
        type: Object as PropType<FormGeneratorInputField>,
        required: true
      },
      // …

To trigger an event, follow the recommendation in your error message:

context.emit("updateValue")
.

For the InputFieldHelper instance, consider restructuring its class implementation:

class InputFieldHelper {
  readonly inputField: {
    inputValue: string | null
  }
  
  constructor(/* … */) {
    this.inputField = reactive({
      inputValue: null
    })
  }
}

Then, utilize it like this:

const helper = new InputFieldHelper(props.value, props.instance, props.formSection, props.isEnable);

const inputField = helper.inputField;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering incorrect month while utilizing the new Date() object

My Objective: I am looking to instantiate a new Date object. Snippet of My Code: checkDates (currentRecSec: RecommendedSection){ var currActiveFrom = new Date(currentRecSec.activeFrom.year,currentRecSec.activeFrom.month,currentRecSec.activeFrom.day ...

script loop causing an embedded form

While trying to include a Hubspot embedded form on a page using a script, I encountered an issue. I utilized onMounted to ensure the form is displayed correctly. However, upon leaving and re-entering the component where the form is located, an additional b ...

Vuetify's v-list-item no longer has spacing issues when using the v-slot:prepend feature

Currently, I am in the process of designing a side navigation using v-navigation-drawer. While most of my items utilize an icon, I also want to create some custom behaviors. Unfortunately, the title in v-slot:title does not align with the title in the v- ...

Exploring ways to establish communication between parent and child components through click events

I am currently working on an Angular 8 application that involves a parent-child relationship. The parent component, DossierCorrespondenceComponent, contains a function that needs to be triggered from within the child component. This is the function in th ...

Using setState as a parameter in a personalized hook in React/Next.js while incorporating TypeScript

I encountered an issue with the following code snippet: import { useState, useEffect } from "react"; type Props = { setState: (value: string) => void; }; const useSomeCustomHook = ({ setState }: Props) => { useEffect(() => { se ...

Can TypeScript ascertain the object's type dynamically based on the key of its proxy name?

I am creating a wrapper class that will handle various operations related to the user entity. These operations include checking if the user is a guest, verifying their permissions, and more. One of the functions I want to implement in this class is an acce ...

Tips for binding to a single input box within an ngFor loop

Can anyone lend a hand with some code? I'm working on a straightforward table using ngFor, but I'm facing an issue with input binding. The problem is that all the input fields generated by ngFor display the same value when typing. How can I preve ...

Enhance your coding experience with TypeScript's autocomplete in Visual Studio Code

After migrating a project from JavaScript to TypeScript, I am not seeing autocomplete suggestions or type hints when hovering over variables in Visual Studio Code editor (Version 1.7.2). Even the basic example provided below does not display any auto-com ...

The data type 'string' does not share any properties with the type 'Properties<ReactText, string & {}>'

My function react element is structured as follows: import { CSSProperties } from 'styled-components' export interface StylesDictionary { [Key: string]: CSSProperties } interface Props { onClick: () => void buttonStyle?: StylesDictionary ...

Is it possible to uncover the mysterious HTML tag within a string of code?

I am searching for the unidentified HTML tag within a given string. For example: '<span>hello</span><p>address</p><span><Enter Your Name></span>' In this case, I need to identify and extract the unknown ...

How can I rectify the issue in TypeScript where the error "not all code paths return a value" occurs?

While developing an application, I encountered an error that says: "not all code paths return a value". The error is specifically in the function named addValues, indicating that the function must return "Obj[] | undefined". Here is the code snippet in qu ...

Optimal method to refresh v-for when updating route in Vue.js seamlessly without having to manually reload the page

What is the best approach to re-render a v-for loop in my Vue.js application when switching to another route? In my scenario, I am using Vuex, vuex-persistedstate, and moment for saving data in localStorage and displaying timestamps like "a moment ago". ...

Is it possible to populate a shopping cart using Vue?

Currently, I am working on integrating a shopping cart feature into a webpage using Vue.js. Upon loading the page, I successfully retrieve a list of items through an API call and display them. However, I am facing challenges in adding items to the cart. ...

VueJS 2 Simplert focuses solely on the component aspect

When I click on a "Submit" button, I want an alert to pop out. To achieve this, I am using Simplert for Vue. The issue arises in my current project, which is a Single Page Application (SPA). The alert only covers the component that triggers it and does no ...

When working with TypeScript in Node, the module ""http"" does not have a default export available

const httpModule = require('http'); httpModule.createServer((req, res) => { res.end('Hello World'); }).listen(3000, () => console.log('Server is running on port 3000')); I've installed @types/node but ...

Discovering and sorting an array in Vue.js based on IDs

Hello everyone, I've been attempting to filter my results using the filter and includes methods but it doesn't seem to be working. Does anyone have a solution for this, perhaps involving includes or something similar? companies ids [1,2,3] user c ...

Is it secure to attach the password field to a data object property in Vue.js?

This particular inquiry has been bothering me lately. Imagine I aim to create a login element for my application (using Vue), containing 2 specific input fields - one for the userID and the other for the password. The focus here is on the security of the ...

Is the value of the incorrect store ref in Vue3 being altered?

Welcome to the store: import { ref } from "vue"; // Storing all the country data export const countriesData = ref(); export const isLoading = ref(true); async function fetchData() { try { isLoading.value = true; const respon ...

Designing an intricate layout with the help of Bootstrap-Vue

After exploring the Vue-Bootstrap panel in my previous question, I implemented the following code snippet to generate a panel: <b-card no-body class="mb-1"> <b-card-header header-tag="header" class="p-1" role="tab"> <b-button b ...

Experience a magical Vue form wizard just like Wilio

Searching for a vuejs wizard form similar to the Wilio Wizard Form. Tried out the Binar Code Wizard Form, but it's not quite what I'm looking for. Need a form wizard with a simple progress bar and step numbers like Wilio. Is it possible to mod ...