What could be causing the issue with Vue's v-model not functioning properly with an array prop?

I created a unique custom component that uses the modelValue prop and emits the update:modelValue event. When I pass an array in the parent component, the list does not update when pressing the button:

CustomComponent.vue

<template>
  <div>
     <button @click="updateIt">Test</button>
  </div>
</template>

<script>
export default {
    props: {
       modelValue: Array
    },
    emits: ["update:modelValue"],
    setup(props, {emit}){
        return {
            updateIt(){
                emit("update:modelValue", [4,5,6])
            }
        }
    }
}
</script>

MainApp.vue

<template>
  <div>
     <custom-component v-model="myArr"/>
     <ul>
         <li v-for="i in myArr" v-text="i"></li>
     </ul>
  </div>
</template>

<script>
import CustomComponent from "./CustomComponent.vue";

export default {
    components: {
        CustomComponent
    },
    setup(props, {emit}){
        const myArr = reactive([1,2,3]);

        return {
            myArr
        }
    }
}
</script>

Even after repeatedly clicking the button, the list does not update as expected. What could be causing this issue?

Answer №1

When using the v-model directive internally, it is transformed into a handler function for the update:modelValue event. This function looks something like this:

$event => ((exp => $event), where exp represents the expression in the directive.

Essentially, when the update:modelValue event occurs, the emitted value is directly assigned to the variable myArr, effectively replacing the entire reactive variable without triggering the reactivity chain since it bypasses the proxy.

If myArr were to be a ref([]), Vue would detect it and the handler function would look like this:

$event => (exp ? (exp).value = $event : null)
, where exp is the expression in the directive.

This means that the value is assigned through the ref proxy, which triggers the reactivity chain.

However, there is no built-in logic to automatically check if the passed expression is an array and perform splice push operations to maintain the original variable. That task needs to be handled manually.

Potential Solutions:

1) Utilize an object key:

 <test-component v-model="myArr.data"/>

 ...

 const myArr = reactive({
    data: [1,2,3]
 });

2) Use a ref:

 <test-component v-model="myArr"/>

 ...

 const myArr = ref([1,2,3]);

3) Implement a custom handler function:

 <test-component :modelValue="myArr" @update:modelValue="onChange"/>>

 ...

 const myArr = reactive([1,2,3]);

 function onChange(newval){
   myArr.splice(0, myArr.length, ...newval);
 }

Answer №2

Solution for Options API Issue

After dealing with a similar issue in the options API, I stumbled upon this effective resolution.

The key problem lies within the proxy object sent to the parent component when emitting the event.

To resolve this, ensure that you transmit a plain array using the following method:

this.$emit('update:modelValue', JSON.parse(JSON.stringify(this.tags)));

In the provided code snippet, the tags array is updated and new values are pushed into it, aiming to have these changes also reflected in the model of the parent component.

Please note: While theoretically this solution should work for the Composition API as well, practical testing has not been conducted yet.

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 causes the error when I use "use client" at the top of a component in Next.js?

Whenever I include "use client" at the top of my component, I encounter the following error: event - compiled client and server successfully in 2.5s (265 modules) wait - compiling... event - compiled client and server successfully in 932 ms (265 modules) ...

What could be the reason for jQuery not loading when vendored in the Sinatra framework?

I'm currently attempting to vendor jQuery in my Sinatra app following a tutorial, but I'm facing issues getting jQuery to work. Typically, I rely on Google's CDN to load jQuery and it always works fine. However, when trying to vendor it, I&a ...

Ensure that the jQuery Knob is set to submit any modifications only after the final adjustment

Utilizing jQuery Knob by anthonyterrien, I have configured the step to be 20. My goal is to transmit the knob's value to the server. The issue arises when the change function is triggered every time the user adjusts the knob using either a right or le ...

The power of Angular controllers lies in their ability to facilitate two-way

Currently, I have a controller that acts as a wrapper for ui-router and manages its flow, similar to a menu bar. When a user clicks on a menu item, a function is triggered that changes the ui-router state and broadcasts an event to the inner controllers. E ...

The alert function is not being triggered upon receiving a JSON response

I am having trouble with an alert not firing a json response. The response appears in firebug, but after upgrading from php4.4.7 to php5.3.5, I encountered this error. It could be my mistake as well. Could someone please review my code and point out where ...

Is there a way for me to redirect back to the original path?

Whenever I utilize <Redirect to="<same_path>" />, a warning pops up: Warning: You tried to redirect to the same route you're currently on: "<path>". In one of my Components, I trigger another Component that prompts for either submis ...

Registering components globally in Vue using the <script> tag allows for seamless integration

I'm currently diving into Vue and am interested in incorporating vue-tabs into my project. The guidelines for globally "installing" it are as follows: //in your app.js or a similar file // import Vue from 'vue'; // Already available imp ...

Guide on how to manage the ROW_CLICK event in a module using vue-tables-2 (vuex)

In my project, there is a module called "csv" responsible for handling csv files, and I am using vue-tables-2 along with vuex: Store setup: -store -modules -csv.js -index.js index.js: Vue.use(Vuex) const store = new Vuex.Store({ modul ...

Creating offspring within offspring

I am currently facing a problem that I believe should be easy to solve. The issue revolves around rendering a component on a particular page. I have set a layout for all child components under the dashboard, but I am uncertain if another layout is needed f ...

What is the reason for the lack of an applied CSS selector?

.colored p{ color: red; } article > .colored{ color:powderblue; } .blue{ color: white; } <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8> <meta name="viewport" content="width=device-width, initi ...

The Material UI Menu does not close completely when subitems are selected

I am working on implementing a Material UI menu component with custom MenuItems. My goal is to enable the closure of the entire menu when clicking outside of it, even if a submenu is open. Currently, I find that I need to click twice – once to close the ...

Sending information to components in Angular using Router

Should I pass data through the angular router to a component, or is it better to use a service? Currently, the component is receiving data in the following way: this.account = activatedRoute.snapshot.data.account ...

Having difficulty transforming a JSON string into a JSON object using Javascript

Currently, I am working on a hybrid mobile application using Angular. I have a string that is obtained from a $http.jsonp request and I am attempting to convert the response into JSON format. After checking the validity of the JSON at , it appears to be va ...

Error in Node.js: [Error: Query parameter should not be empty]

I've been recently focusing on a project that involves sending the required name to my profile.js file using a POST request. However, whenever I try to access console.log(req.body.bookName) (as the data being sent is named bookName), it shows an error ...

Error: Loop Program Encountered Unexpected Token Syntax

Every time I attempt to run this code, a syntax error (unexpected token) appears. As someone who is still learning JavaScript, I am struggling to identify the root cause of this issue. var x = 1; var example = function(){ for(var y = 0; y < ...

how can I include an AngularJS variable as a parameter in an onclick function?

I attempted to utilize an AngularJS variable as an argument value inside onclick() in order to invoke a JavaScript function. Can someone provide me with instructions on how to achieve this? Here is my code: <div onclick="deleteArrival({{filterList.id} ...

Position object in the middle using jQuery and CSS

Trying to center an absolutely positioned object horizontally using CSS and jQuery is proving to be a challenge. The use of jQuery is necessary due to the varying widths of the objects. Hover over the icons in my jsFiddle to see the issue. Check out the j ...

Creating an Angular 7 Template using HTML CSS and Javascript

I recently acquired a template that comes with HTML, CSS, and Javascript files for a static webpage. My goal is to integrate these existing files into my Angular project so I can link it with a Nodejs application to create a full-stack webpage with backend ...

What is the method for displaying the value of a textarea?

I am relatively new to the world of coding, but I have already delved into HTML, CSS, and basic DOM scripting. My goal is simple - I want to create a comment box where people can leave messages like in a guestbook. However, when I input text and click on ...

Issues encountered with rest arguments while setting up gtag

I am currently working on implementing a Google Tag loading script using TypeScript. const GTAG_ID = 'ID'; const script = document.createElement('script'); script.src = `https://www.googletagmanager.com/gtag/js?id=${GTAG_ID}`; ...