Creating powerful Vue event handlers with composable functions

I am currently working with Vue 2.0, ES6, and Webpack.

In my project, I have a Parent component and several child components called text-input. Each text-input emits a change event that should modify a different property inside the Parent component. For instance, the Parent component has a data object named info, which contains properties like name, email, etc.

My goal is to use the same function for the @change event of each text-input in order to set the correct property (name, email, etc.) dynamically.

<text-input
   @change="alterProperty('name')">  
 </text-input>
 <text-input
   @change="alterProperty('email')">  
 </text-input>

The method in my Parent component looks like this:

alterProperty (property) {
  return (changeValue) => {
    this.info[property] = changeValue
  }
}

However, I am facing some challenges in making this work. It seems like there might be an issue with how Vue handles things. If anyone has any insights or solutions, I would greatly appreciate the help.

Thank you!

Answer №1

Take a look at this jsFiddle example: https://jsfiddle.net/mani04/2mmbsyy3/

The functionality works exactly as expected. Here is an example of how the text-input component is utilized:

<text-input :value="userInfo.name" @change="alterProperty('name', $event)"></text-input>

Important note: The method alterProperty is an inline method directly called in the @change event handler. It will not receive the default $event parameter unless explicitly included. This is a crucial aspect missing from your code.

For more information, refer to: https://vuejs.org/guide/events.html#Methods-in-Inline-Handlers

In the provided jsFiddle demonstration, $event only contains event arguments from the child component and not a DOM event. My alterProperty method (within the parent component) functions as follows:

alterProperty: function(propToChange, newValue) {
    this.userInfo[propToChange] = newValue;
}

The jsFiddle also presents the object within the parent component, showcasing the expected modifications.

Edit: Additional notes

It is advised that your child component should not directly bind this.value to the input element, as this.value is passed via props. Attempting to do so may result in a console error notification similar to:

[Vue warn]: Avoid mutating a prop directly...

To circumvent this issue, I have implemented a local computed property - textFieldValue, which includes getter and setter methods. While the getter simply returns this.value, the setter effectively triggers the change event back to the parent component without altering this.value received through props.

Answer №2

To achieve effectiveness, I have created 2 fiddles. One method involves using v-on and emitter to facilitate communication between child and parent components. The other method is to directly update the parent data within the child component.

I personally recommend the first method.

Take a look at the first example, which utilizes the v-on and emitter approach: https://jsfiddle.net/seaify/p8fh108j/

Vue.component('text-input', {
    props: ["parent_field"],
    template: `
        <input type="text" v-model="text">
    `,
    data: function() {
      return {text: ''}
    },
    watch: {
       text: function(value, old_value) {
          this.$emit('update_parent', this.parent_field, value)
       }
    }
});

Vue.component('my-app-form', {
    template: `
        <div class="my-app-form">
            <div class="my-text-input">
                Name: <text-input parent_field="name" v-on:update_parent='update_self'></text-input>
            </div>
            <div class="my-text-input">
                Email: <text-input parent_field="email" v-on:update_parent='update_self'></text-input>
            </div>
            <div class="result">Result: name = {{name}}, email = {{email}}</div>
        </div>

        `,
    methods: {
       update_self: function(key, value) {
       this[key] = value
      }
    },
    data: function() {
        return {
                name: "",
                email: ""          
        }
    },
});

new Vue({
    el: '#app',
    template: `
        <div>
            <my-app-form></my-app-form>
        </div>
    `,
});

Here is the link to the second example where the parent component is directly updated without communication: https://jsfiddle.net/seaify/jczowb54/10

Vue.component('text-input', {
    props: ["parent_field"],
    template: `
        <input type="text" v-model="text">
    `,
    data: function() {
      return {text: ''}
    },
    watch: {
       text: function(value, old_value) {
            this.$parent[this.parent_field] = value
       }
    }
});

Vue.component('my-app-form', {
    template: `
        <div class="my-app-form">
            <div class="my-text-input">
                Name: <text-input parent_field="name"></text-input>
            </div>
            <div class="my-text-input">
                Email: <text-input parent_field="email" ></text-input>
            </div>
            <div class="result">Result: name = {{name}}, email = {{email}}</div>
        </div>

        `,
    data: function() {
        return {
                name: "",
                email: ""          
        }
    },
});

new Vue({
    el: '#app',
    template: `
        <div>
            <my-app-form></my-app-form>
        </div>
    `
});

A special thanks to Mani for providing the original fiddle, as I have forked it and made some code updates.

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

Experimenting with Vue in conjunction with a web component

I am facing an issue with astrouxds web components in my application. During testing, I am receiving a warning that needs to be resolved. Additionally, I need help on how to properly assert a value in the web component. console.error node_modules/vue/dis ...

Tips for using rspec to test front end functionality?

In my Rails project, I have incorporated Vue.js using only the core library. Currently, most forms in the project are developed with Vue.js. When testing front-end features like form filling or validations using feature tests in RSpec, I found it to be qui ...

Running a function in a different vue file from an imported file - A step-by-step guide

Learning the ropes of vue.js, I am working with two separate vue files: First file: import second from second.vue; export default{ component: {second}, data() {return{ data: 'data', }} methods: { function f1{ console.log(t ...

Creating a dynamic MPTT structure with expand/collapse functionality in a Django template

I am looking for a way to display my MPTT model as a tree with dropdown capability (open/close nodes with children) and buttons that can expand/collapse all nodes in the tree with just one click. I have searched for examples, but the best I could find is ...

Switch out an item within a list of objects with a different item

I have a variable called this.rows that contains a collection of items. There is a real-time item being received from the server, which matches one of the items in the this.rows object collection. How can I replace an item with new values? Below is an ex ...

Having trouble with Laracast Video(Push Events to the Client) error?

After following a video tutorial on event handling, everything was working perfectly until the last minute when I tried to display the user name in real time on a list view. Although I could see each object in my console using console.log('users' ...

After modifying environment variables in Vue.js, the application still refers to the previous values

Currently, I am working on a Vue.js project where I have a .env.development file with various VUE_APP_* environment variables. Despite changing the values of some variables, the Vue.js code continues to reference the previous values. I have attempted mult ...

Unable to extract data from object list in Vue.js

Hi, I'm new to coding and trying to implement a function that shows related articles using Java with REST api. However, when I call the API using axios, the data is not being displayed on the view. I have checked the API and confirmed that it is retu ...

An error occurred: gyp ERR! stack - The command `python -c import sys; print "%s.%s.%s" % sys.version_info[:3]` has failed

While attempting to npm install in a Vue project, I encountered an error even after running vue create (name): npm ERR! gyp verb check python checking for Python executable "c:\Python310\python.exe" in the PATH npm ERR! gyp verb `which` ...

Issues with running Vue commands have been reported in Git-Bash, however they seem to work fine in

Whenever I check the version of Vue in my Terminus bash by running vue --version, here's the output I receive: $ vue -v /bin/sh: /Users/kirkb/AppData/Local/Yarn/bin/../Data/global/node_modules/.bin/vue: No such file or directory In PowerShell, when I ...

vue.js throwing error: Unable to access 'getters' property of an undefined object

Within the Form component.vue, there is a substitution of the event object from the getter into the v-model: <template> <form @submit.prevent="submitForm"> <div class="form-group row"> <div c ...

Automatically adjust div dimensions as window is resized

I am attempting to dynamically set a height in pixels for my container when its size changes. I have managed to display the size as text, which successfully updates when the container is resized. However, the height attribute on my container does not updat ...

Using Vue.js to dynamically populate all dropdown menus with a v-for loop

Getting started with vue.js, I have a task where I need to loop through user data and display it in bootstrap cols. The number of cols grows based on the number of registered users. Each col contains user data along with a select element. These select ele ...

What are the most effective techniques for combining Vue.JS and Node.js backends into a single Heroku container?

I came across an interesting blog post today that discusses a method for deploying React applications. The author begins with a Node project and then creates a React project within a subfolder, along with some proxy configuration. About 10 days ago, I did ...

Retrieving data from an API using VUEJS3 and Typescript

I am facing an issue with displaying data in my template. When I try to do so, the screen remains blank. I am using Vue.js 3 with TypeScript and I am fairly new to this technology. <template> <div> <img :src="datas[0].imag ...

What are the steps to analyze all attributes of a Vue.js state object using the Chrome Devtools console?

Every time I try to inspect live data on a Vue instance in Chrome, I find myself having to click into the object just to see any data because of how all the values have been converted to getters and setters. This image illustrates my frustration. After cl ...

What is the most effective strategy for managing dependencies for npm packages?

I am currently working on extracting a few Vue.js components from the main application and converting them into an npm package stored in a repository. This package will be imported and utilized across two different websites. To bundle everything, I am util ...

What is the best way to implement a multi-row form in Vue.js?

Form Structure: <card-wrapper v-for="(passenger, index) in form.passenger" :key="index" :icon="['fas', 'user']" :title="`Passenger ${index + 1}`" class="mb-5" > <validation-observer ...

What are the steps to enable a Vue component to handle its own transitions?

I am looking for a way to handle enter and leave animations in Vue when components are mounted or removed. My goal is to consolidate all the animation code into its own component for better organization. <template> <transition @enter="enter" ...

Chorme is throwing a CSRF token mismatch error when working with Laravel API Sanctum

Having an issue with my Vue app and backend Laravel setup. I am using SPA Authentication for authentication. Everything works fine in localhost, but when I deployed it to the server, there are some issues. After sending a login request to sanctum/csrf-co ...