In Vue using Typescript, how would I go about defining a local data property that utilizes a prop as its initial value?

When passing a prop to a child component in Vue, the documentation states:

The parent component updates will refresh all props in the child component with the latest value. Avoid mutating a prop inside a child component as Vue will warn you in the console.

Use the prop to pass an initial value; then have the child component treat it as a local data property. Define a local data property using the prop's initial value:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

We are working with Typescript. The syntax for defining a local data property is as follows (from my understanding):

<script lang="ts">
import Vue from 'vue'
import { Component } from 'vue-property-decorator'

@Component
export default class App extends Vue {
  // Data property
  myDataProperty: string;
</script>

The syntax for a prop is as follows:

@Component
export default class App extends Vue {
  // Making "exampleProperty" a component prop with the default value of 'Example'
  @Prop({default: 'Example'})
  exampleProperty: string
}

Thus, we followed the documentation and ended up with:

parentComponent.vue

<template>
  <childComponent testProperty='test' />
</template>

childComponent.vue

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class childComponent extends Vue {
  @Prop(
    {
      default: 'notTest',
      validator: (component) => {
        return [
          'notTest',
          'test',
        ].indexOf(component) > -1;
      },
    },
  )
  testProperty!: string;
  testProperty = this.testProperty;
</script>

This resulted in an error `Duplicate identifier testProperty` as expected. Therefore, we tried:

...
      testProperty!: this.testProperty;
...

which led to the following error message:

Duplicate identifier 'testProperty'. Property 'testProperty' has no initializer and is not definitely assigned in the constructor. Subsequent property declarations must have the same type. Property 'testProperty' must be of type 'this', but here has type 'any'.

Consequently, I decided to try the "vue-class-component" decorator.

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component({
  data: function(){
    return {
      testProperty: this.testProperty,
    }
  }
})
export default class childComponent extends Vue {
  @Prop(
    {
      default: 'notTest',
      validator: (component) => {
        return [
          'notTest',
          'test',
        ].indexOf(component) > -1;
      },
    },
  )
  testProperty!: string;
  testProperty = this.testProperty;
</script>

This resulted in the error

Property 'testProperty' does not exist on type 'Vue'.

I intend to do

this.testProperty = 'newProperty'
in a handler at some point, but cannot due to directly modifying a prop.

How can I define a local data property that uses a prop as its initial value in Typescript?

EDIT:

If I simply define the prop without attempting to define a local data property using it as the initial value, and then execute

this.testProperty = 'test'

in a handler, Chrome console displays this error:

vue.runtime.esm.js[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "testProperty"

Answer №1

In a nutshell, the issue you're encountering stems from already defining this.testProperty as a prop. Utilizing testProperty = this.testProperty creates a circular reference. Simply using the @Prop decorator handles mapping the attribute in the template to the variable.

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class childComponent extends Vue {
  @Prop(
    {
      default: 'notTest',
      validator: (component) => {
        return [
          'notTest',
          'test',
        ].indexOf(component) > -1;
      },
    },
  )
  testProperty!: string;

  // Map prop to local data property
  testPropertyLocal = this.testProperty;
</script>

Furthermore, keep in mind that VueJS properties should be kebab-case in templates and camelCase in JS. So, make sure to adjust your child component reference to:

<template>
  <childComponent test-property='test' />
</template>

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

Fluctuating updated site (ajax)

What method do you recommend for maintaining the data in a table on a page current? Currently, I am using a timer that connects to the server via ajax every 2 seconds to check for updates. Is there a way to trigger an event or function only when the cont ...

Lazy loading with Vue router seems to be having issues within the Vite environment, as an error is being thrown mentioning an unknown

I have successfully implemented the code below in Vue router and it works flawlessly in Vue-CLI. import store from "./../../store/index.js"; function getView(view) { return () => import(`@/views/settings/${vi ...

Arrange a collection of objects by two criteria: the end time, followed by the status in accordance with the specified array order if the end times are equal

Is this the best method to arrange data by using infinity? I gave it a try but it doesn't quite meet my requirements. data = [{ "status": "Accepted", "endTime": "" }, { "status": "New", ...

Automatically scroll the chat box to the bottom

I came across a solution on Stackoverflow, but unfortunately, I am having trouble getting it to work properly. ... <div class="panel-body"> <ul id="mtchat" class="chat"> </ul> </div> ... The issue lies in the JavaScript t ...

Which is the better choice for simply invoking a service method - subscribe or toPromise?

When implementing the search method below, I simply assign the value of BehaviourSubject in the service. However, I am unsure whether it is possible to execute this operation without using either subscribe() or toPromise() after the .pipe() block in the ...

You are unable to assign mutations in Vuex

Dealing with a peculiar problem where "val" and "ok" can be used within "console.log()", but for some reason, state.user cannot be assigned any value. However, state.user does display 'ok' on the website. export const state = () => ({ user: ...

Using PHP to upload images through AJAX increases efficiency

Worked tirelessly on this script all night still unable to fix the bug. The issue is that when I select an image and click upload, it uploads the current image file. Then, if I select another image and click upload, it uploads two new files along with the ...

Submit data from one form to another form located within an iframe

I am currently using a JX Browser that allows content to be displayed in an iframe. My goal is to automatically transfer the username and password of a user logging into my ticketing software to another form within an iframe. The page within the iframe is ...

Validating ReactJS properties

Transitioning from ReactJs to React-Native, I came across this function structure in a react-native button code by Facebook: class Button extends React.Component<{ title: string, onPress: () => any, color?: ?string, hasTVPreferredFocus?: ?bo ...

Challenges surrounding asynchronous functionality in React hooks

I've been facing some issues with this code and have resorted to debugging it using console.log(). However, the results I'm getting are not making any sense. Can someone help me identify what's wrong with this code? I noticed that my console ...

A guide on extracting data from a mongoose model and assigning it to a variable in a manner similar to the MVC design pattern

Below is an example of MVC framework code in PHP. I'm seeking advice on how to implement a similar process in Node.js using Mongoose. I am working with Node.js, MongoDB, and REST API development. Controller file: <?php class Myclass { public fu ...

How to style a div for printing using CSS

Currently, I am working on a project that has already been completed but now requires some enhancements. To give you an overview, the project includes a search functionality that displays additional details upon clicking on the displayed name in the result ...

Is there a way to extract only the value from the most recent request?

While working with VueJS, I have a handler for changes in an input field that looks like this: inputHandler(url, params){ const p = new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('POST&ap ...

Troubleshooting error in Angular 5 with QuillJS: "Parchment issue - Quill unable to

I've been working with the primeng editor and everything seems fine with the editor itself. However, I've spent the last two days struggling to extend a standard block for a custom tag. The official documentation suggests using the quilljs API fo ...

Customizing Webpack 4's Entry Point

Below is the layout of my project: -node_modules -src -client -js -styles -views -index.js -webpack.config.js -server -.babelrc -package -package-lock -README.md -webpack ...

Issue encountered with Fabric js: Unable to apply pattern fill to a group of rectangles

Greetings, I am in need of some assistance with a coding issue. I have a for loop that generates and adds multiple rectangles to a fabric js canvas. To set a texture for each rectangle, I am using the following code snippet. var rect = new fabric.Rect( ...

Generating HTML table rows dynamically in Angular based on the number of items stored in a $scope variable

In my current project, I am utilizing Angular to dynamically populate data in an HTML table. Instead of manually coding each row for display, I am in need of a solution that allows me to programmatically define each HTML row. The Angular controller snippet ...

`Apply event bindings for onchange and other actions to multiple elements loaded via ajax within a specific div`

My form includes various input fields, dropdowns, and text areas. Upon loading, jQuery locates each element, sets its data attribute to a default value, attaches an onchange event, and triggers the change event. The issue arises when some dropdowns are d ...

Guide to executing a batch file using electron

I've been struggling all morning to find a solution. I've gone through several tutorials, but I still can't wrap my head around how this should work. In my Electron app, there is a button that, when clicked, should execute a batch file (hpm ...

How to Retrieve an Array from a Promise Using Angular 4 and Typescript

I am encountering difficulties when trying to store data from a returned promise. To verify that the desired value has been returned, I log it in this manner: private fetchData() { this._movieFranchiseService.getHighestGrossingFilmFranchises() ...