After cloning the variable from props, the Vue 3 Composition API variable becomes undefined

I have a main component containing code and tables, including a modal that is displayed based on a boolean value.

The main component features the following modal:

 <ConfirmPaymentModal
    ref="confirmPaymentModal"
    :invoice="markAsPaidInvoice"
    :max-amount="maxAmount"
    :is-dialog-visible="markAsPaidVisible"
    @update:is-dialog-visible="markAsPaidVisible = $event"
    @submit="markAsPaidModal(markAsPaidInvoice.id, $event, false )"
  />

This is how I've set up the ConfirmPaymentModal:

<script setup>
import { formatThousands } from '@layouts/utils'

const props = defineProps({
    isDialogVisible: {
        type: Boolean,
        required: true,
    },
    invoice : {
        type: Object,
        required: true,
    },
    maxAmount : {
        type: Number,
        required: true,
    },
})

const emit = defineEmits([
    'submit',
    'update:isDialogVisible',
])

const totalAmount = ref(props.invoice.total_amount)
</script>

The goal is to set a maximum value for :

<VTextField
    v-model="props.invoice.total_amount"
    type="number"
    density="compact"
    :label="'Total ' + props.invoice.currency"
 />

I initially attempted to achieve this within a watcher:

watch(() => props.invoice.total_amount, newValue => {
    if (newValue > props.maxAmount) {
        props.invoice.total_amount = props.maxAmount
    }
})

However, I am consistently encountering an issue where totalAmount is undefined. I believe I need to clone the value because I cannot directly modify props.invoice.total_amount. Can anyone provide guidance on how to properly handle this?

Thank you!

Note: Although my solution eventually worked, I'm questioning whether it's appropriate to change prop values. Am I mistaken in thinking so?

Answer №1

If you need to establish a two-way binding, one way to achieve this is by binding the text field to a writable computed property that retrieves the prop and then emits the new value when it's set:

<script setup>
import { formatThousands } from "@layouts/utils";

const props = defineProps({
  isDialogVisible: {
    type: Boolean,
    required: true,
  },
  invoice: {
    type: Object,
    required: true,
  },
  maxAmount: {
    type: Number,
    required: true,
  },
});

const emit = defineEmits(["submit", "update:isDialogVisible", "update:invoice"]);

const totalAmount = computed({
  get() {
    return props.invoice.totalAmount;
  },
  set(value) {
    emit("update:invoice", {
      ...props.invoice,
      totalAmount: value,
    });
  },
});
</script>
<template>
  <VTextField v-model="totalAmount" type="number" density="compact" :label="'Total ' + props.invoice.currency" />
</template>

In the parent component, include

v-model:invoice="markAsPaidInvoice"
:

<ConfirmPaymentModal
    ref="confirmPaymentModal"
    v-model:invoice="markAsPaidInvoice"
    :max-amount="maxAmount"
    :is-dialog-visible="markAsPaidVisible"
    @update:is-dialog-visible="markAsPaidVisible = $event"
    @submit="markAsPaidModal(markAsPaidInvoice.id, $event, false )"
  />

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

What is the best way to control the amount of rows displayed in my gallery at any given time?

I need help with customizing my gallery that is dynamically generated from a directory using PHP. My goal is to display only 2 rows of 4 images each, totaling 8 images, with a "show more" button for loading additional rows. How can I set a limit on the n ...

What is the best way to check for changes in value using the onchange

The function is encountering an error and failing to execute. Despite my attempts to check for the onchange property in order to prevent errors, I keep receiving an error message stating "Cannot read property 'onchange' of undefined." Below i ...

Using ng-repeat and selectize in AngularJS to populate a multi-select drop-down with values and set selected values

In this instance, I was able to achieve pure HTML select multiple functionality by using this example (JS Bin of pure html select tag). However, instead of sticking to just the pure HTML approach, I opted to use the Selectize plugin. The confusion arose w ...

Using jQuery to initiate a page load into a new page within the WorkLight platform

I need help redirecting to a new page when the current page is loaded. My website is built using jQuery mobile in combination with WorkLight. Index.html: <body> <div data-role="importpages" id="pageport"> </div> </body> ...

"Enhance Your Sublime 3 Experience with a Jade Syntax Highlighter, Linting, Auto Complete, and

After trying out the recommended packages for Sublime Text, I'm still not satisfied with how they handle syntax highlighting, code linting, and auto suggestion. Could anyone recommend a comprehensive package specifically for Jade? ...

Is it possible to verify the user's authentication by confirming the presence of a JWT in their localStorage?

I am currently working on a project that requires JWT authentication. I have set up a registration form and login page where users receive an authorityToken and it is saved in localStorage. Once the user logs into their account : ` $("#btnLogin").click( ...

Obtain the dynamic identifier of an element within every block using jQuery in a rails application

Let me illustrate my issue with a simple example. I am currently developing a recipe application. Within the show partial that loads via AJAX, I have the following setup: _show.html.erb <% @recipe.ingredients.each do |ingredient| %> <div class ...

Unable to assign a className to a personalized React component - troubleshooting needed!

I have a component that relies on another component. I am trying to pass CSS positioning from the outer component to the inner one by using the following code: import OptionsMenu from './OptionsMenu' import { withStyles } from 'material-ui/ ...

I am experiencing difficulty with the function from flip.to not functioning properly on my Next.js project

I was given this script by flip.to <script> !function(b,e){ (b[e] = b[e] || []).push({ flipto: { bookingEngine: "Demo", companyCode: "XX", code: "YYYY", ...

What methods can I implement to showcase random images in JavaScript using a JSON array value?

I am currently working on a fun avatar generator project. The challenge I'm facing is that each hairstyle consists of two parts (front and back), and when loaded randomly, the colors don't always match. To tackle this issue, I have organized the ...

"Vue's prevention of default behavior in router-link element is effective in Chrome, but it seems to

My component uses a router-link as the root tag, and I'm trying to prevent its default link behavior in case there are issues with JavaScript or if it's disabled. In Chrome, I was able to achieve this using event modifiers like: @click.native.ca ...

What is the best way to recycle Vue and Vuetify code?

<script> export default { data () { return { my_alert: false, text: '', color: 'success' } }, methods: { openAlt (text, color) { this.text = text this.color = color this.my_ale ...

Is it better to utilize angular's $interval or a promise to execute code upon completion of an api call?

I am facing an issue with a slow api call in my code. $http.jsonp(url, { params: { 'client': 'translate_about', 'alpha': 1, 'hl': 'en' } }) .success(function (data) { ...

Learn how to run javascript code using Nodejs child_process and Meteor

Is it possible to use the child_process module to execute Meteor server-side code instead of just Linux commands? I am interested in using spawn to create a separate process for running my loop. The loop involves logging a message every minute. myLoop(){ ...

Dealing with numerous promises simultaneously using AngularJS Factory

I have created a code that makes multiple $http calls recursively and saves all the promises it returns in an array. Then, I resolve all of them and save the responses in another array. Now, my question is: How can I efficiently return this final array to ...

Tips for successfully transferring the nested service and retrieving the response from an Angular factory to a controller

After making the Http Request and receiving the response from the first Service call, I then pass that response from the first service into the second service and receive the response back to the controller. Now that I have the response, I need to find a ...

Tips for retaining a number even when the page is refreshed

Is there a way to keep the number increasing even after refreshing the webpage? Currently, the number resets every time the page is refreshed. Any suggestions on how to fix this? Here is the number <form method="POST"> &l ...

An issue arose while attempting to pin a file on IPFS: A TypeError [ERR_INVALID_ARG_TYPE] was encountered, specifying that the argument "url" must be a string data type

Adding the files to another project resulted in an error that I am struggling to understand. When running "node scripts1/runScript.js", the error message received is as follows: Error occurred while pinning file to IPFS: TypeError [ERR_INVALID_ARG_TYPE]: ...

The issue with updating state in React using dispatch within the same method is not working

Initially, I had a situation where the state was updating correctly with two separate methods (onClick). const sizesMeasureChoise = useSelector(getSizesMeasureChoise); const chooseMeasure = (measure) => { dispatch(setSizeMeasureChoise(measure)); ...

What is preventing the buttons from filling the entire space of the parent element in this case?

https://i.stack.imgur.com/kbiWi.png I'm trying to figure out how to make the Repos and Stars buttons fill the entire height of their parent container, similar to the Github icon. Unfortunately, the code below is not achieving this effect. I attempted ...