transfer the value of a method to a different component

In my Component called IncomeList, there is a method named sumValue. This method simply adds different numbers together to produce one value, for example 3+5 = 8. Similarly, in another Component named OutputList, the same logic is applied but with a method called sumValueOutput. Now, I want to utilize both values in a new component named WinTotal. I've attempted using props and Vuex, however, I haven't been successful so far and I'm unsure where to begin. Thank you for your assistance!

IncomeList:

<template>
<div class="container-income">
    <button class="btn btn-info" @click="showModal">show modal</button>
    <div class="hidden-container-income" id="test123">
    <input type="text" class="income-input" placeholder="What needs to be done" v-model="newIncome" @keyup.enter="addincome">
    <input type="text" class="value-input" placeholder="€" v-model="newIncomeValue" @keyup.enter="addValue">
    <transition-group name="fade" enter-active-class="animated fadeInUp" leave-active-class="animated fadeOutDown">
        <income-item v-for="income in incomesFiltered" :key="income.id" :income="income"
                   @removedIncome="removeincome">
        </income-item>
    </transition-group>

    <div class="extra-container">
        <div><label><input type="checkbox" style="display: none" :checked="!anyRemaining" @change="checkAllincomes"></label></div>
        <div>{{ remaining }} elements</div>
    </div>
    <div class="sum-container">
        <div><label> Total Income: </label></div>
        <div>{{ sumValue }} €</div>
    </div>
  </div>
</div>
    </template>
    <script>
    import IncomeItem from './IncomeItem'
    export default {
    name: 'income-list',
    components: {
        IncomeItem,
    },
    data () {
        return {
            newIncome: '',
            newIncomeValue: '',
            idForincome: 3,
            incomes: [
                {
                    'id': 1,
                    'title': 'Finish Vue Screencast',
                    'value': 300,
                    'completed': false,
                    'editing': false,
                },
                {
                    'id': 2,
                    'title': 'Take over world',
                    'value': 315,
                    'completed': false,
                    'editing': false,
                },
                {
                    'id': 3,
                    'title': 'Excellent',
                    'value': 313,
                    'completed': false,
                    'editing': false,
                },
            ]
        }
    },
    computed: {
        remaining() {
            return this.incomes.filter(income => !income.completed).length
        },
        anyRemaining() {
            return this.remaining != 0
        },
        incomesFiltered() {
            return this.incomes
        },
        sumValue() {
            return this.incomesFiltered.reduce((a, c) => a + c.value, 0)
        },
    },
    methods: {
            addincome() {
                if (this.newIncome.trim().length == 0) {
                    return
                }
                this.incomes.push({
                    id: this.idForincome,
                    title: this.newIncome,
                    value: this.newIncomeValue,
                    completed: false,
                })
                this.newIncome = ''
                this.newIncomeValue = ''
                this.this.idForincome++
            },

        removeincome(id) {
            const index = this.incomes.findIndex((item) => item.id == id)
            this.incomes.splice(index, 1)
        },
        checkAllincomes() {
            this.incomes.forEach((income) => income.completed = event.target.checked)
        },
        clearCompleted() {
            this.incomes = this.incomes.filter(income => !income.completed)
        },
        finishedEdit(data) {
            const index = this.incomes.findIndex((item) => item.id == data.id)
            this.incomes.splice(index, 1, data)
        },
        //Same for Value
        addValue() {
            if (this.newIncomeValue.trim().length == 0) {
                return
            }
            this.incomes.push({
                id: this.idForincome,
                title: this.newIncome,
                value: this.newIncomeValue,
                completed: false,
            })
            this.newIncome = ''
            this.newIncomeValue = ''
            this.this.idForincome++
        },
        showModal () {
            if (document.getElementById('test123').style.display == 'none' ) {
                document.getElementById('test123').style.display = 'block';
            }
            else {
                
                
document.getElementById('test123').style.display = 'none'
            }
        },
    },
};
                               </script>

OutputList:

<template>
<div class="container-output1">
    <button class="btn btn-info1" @click="showModal">show modal</button>
    <div class="hidden-container-output1" id="test1231">
        <input type="text" class="output-input1" placeholder="What needs to be done" v-model="newOutput" @keyup.enter="addoutput">
        <input type="text" class="value-input1" placeholder="€" v-model="newOutputValue" @keyup.enter="addValue">
        <transition-group name="fade" enter-active-class="animated fadeInUp" leave-active-class="animated fadeOutDown">
            <output-item v-for="output in outputsFiltered" :key="output.id" :output="output"
                         @removedoutput="removeOutput">
            </output-item>
        </transition-group>

        <div class="extra-container1">
            <div><label><input type="checkbox" style="display: none" :checked="!anyRemaining" @change="checkAlloutputs"></label></div>
            <div>{{ remaining }} elements</div>
        </div>
        <div class="sum-container1">
            <div><label> Total Output: </label></div>
            <div>{{ sumValueOutput }} €</div>
        </div>
    </div>
</div>
   </template>

   <script>
import OutputItem from './OutputItem'
export default {
    name: 'output-list',
    components: {
        OutputItem,
    },
    data () {
        return {
            newOutput: '',
            newOutputValue: '',
            idForOutput: 3,
            outputs: [
                {
                    'id': 1,
                    'title': 'Finish Vue Screencast',
                    'value': 300,
                    'completed': false,
                    'editing': false,
                },
                {
                    'id': 2,
                    'title': 'Take over world',
                    'value': 315,
                    'completed': false,
                    'editing': false,
                },
                {
                    'id': 3,
                    'title': 'Excellent',
                    'value': 311,
                    'completed': false,
                    'editing': false,
                },
            ]
        }
    },
    computed: {
        remaining() {
            return this.outputs.filter(output => !output.completed).length
        },
        anyRemaining() {
            return this.remaining != 0
        },
        outputsFiltered() {
            return this.outputs
        },
        sumValueOutput() {
            var outputValue = this.outputsFiltered.reduce((a, c) => a + c.value, 0);
            return outputValue;
        },
    },
    methods: {
        addOutput() {
            if (this.newOutput.trim().length == 0) {
                return
            }
            this.outputs.push({
                id: this.idForOutput,
                title: this.newOutput,
                value: this.newOutputValue,
                completed: false,
            })
            this.newOutput = ''
            this.newOutputValue = ''
            this.this.idForOutput++
        },

        removeOutput(id) {
            const index = this.outputs.findIndex((item) => item.id == id)
            this.outputs.splice(index, 1)
        },
        checkAlloutputs() {
            this.outputs.forEach((output) => output.completed = event.target.checked)
        },
        clearCompleted() {
            this.outputs = this.outputs.filter(output => !output.completed)
        },
        finishedEdit(data) {
            const index = this.outputs.findIndex((item) => item.id == data.id)
            this.outputs.splice(index, 1, data)
        },
        //Same for Value
        addValue() {
            if (this.newOutputValue.trim().length == 0) {
                return
            }
            this.outputs.push({
                id: this.idForOutput,
                title: this.newOutput,
                value: this.newOutputValue,
                completed: false,
            })
            this.newOutput = ''
            this.newOutputValue = ''
            this.this.idForOutput++
        },
        showModal () {
            if (document.getElementById('test1231').style.display == 'none' ) {
                document.getElementById('test1231').style.display = 'block';
            }
            else {
                document.getElementById('test1231').style.display = 'none'
            }
        }

    }
}
            </script>

Answer №1

There are a couple of effective ways to pass data between components in Vue:

1) Using a Bus

In Vue, you can easily pass data from a child component to its parent by emitting events. Simply emit the data in the child component:

this.$emit('event-name', payload)

And listen for the event in the parent to receive the data:

<child-component @event-name="doSomething($event)" />

However, passing data directly between two components can be challenging. One workaround is to create a shared instance called a Bus, which allows you to emit events between the components.

Creating a Bus is simple and requires only a few lines of code:

// Bus.js
import Vue from "vue";

export const Bus = new Vue();

In your child components (IncomeList and OutputList), import the Bus and emit events with the desired values:

import { Bus } from "@/Bus";

sumValue() {
    const sumVal = this.incomesFiltered.reduce((a, c) => a + c.value, 0);
    Bus.$emit("sumvalue-change", sumVal);
    return sumVal;
}

In the WinTotal.vue component, import the Bus and listen for these events within the created hook:

created() {
    Bus.$on("sumvalue-change", (sumvalue) => (this.sumValue = sumvalue));
}

You can now use the updated values in WinTotal as needed. Check out this sandbox for a demonstration.

2) Utilizing VueX

An alternative solution is to leverage VueX for passing data between components. If you're familiar with VueX, this method may be simpler to implement compared to using a Bus.

Create state values for sumValueIncome and sumValueOutput in your store, and mutations to update them:

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    sumValueIncome: null,
    sumValueOutput: null
  },
  mutations: {
    updatesumValueIncome(state, newvalue) {
      state.sumValueIncome = newvalue;
    },
    updatesumValueOutput(state, newvalue) {
      state.sumValueOutput = newvalue;
    }
  },
});

In IncomeList and OutputList, update the values using VueX mutations:

sumValueIncome() {
  const sumValueIncome = this.incomesFiltered.reduce((a, c) => a + c.value, 0);
  this.$store.commit("updatesumValueIncome", sumValueIncome);
  return sumValueIncome;
}

In WinTotal, utilize the mapState helper to access the dynamically updated values:

<script>
import { mapState } from "vuex";

export default {
  computed: mapState(["sumValueIncome", "sumValueOutput"]),
};
</script>

By following these steps, you can effectively pass and manage data between components using VueX. Take a look at this sandbox for a practical example of this approach.


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

Can JSON encoding in a URL pose a risk of XSS attacks?

To ensure my application has URL-friendly capabilities, I am storing its context as a JSON within the URL. This results in something like: http://mysite.dev/myapppage/target#?context={%22attr1%22%3A{%22target_id-0%22%3A{%22value%22%3A%223%22%2C%22label%2 ...

Refresh the calendar to retrieve updated information

Utilizing the "events" elements of fullcalendar to retrieve data dynamically has been successful so far and I am satisfied with it. However, I am facing a challenge in passing a GET/POST parameter to the PHP page and refreshing the call to incorporate the ...

Adjusting font sizes in JavaScript causes the text to resize

Within my HTML pages, I am adjusting the font size using JavaScript code like this: "document.body.style.fontSize = 100/50/20" However, whenever the font size changes, the text content on the page moves up or down accordingly. This can be disorienting for ...

Guide to aligning the orientation of an object with a given normal vector using three.js

Imagine I have a car object where the z-rotation is positioned to face the direction it's moving in. This car is situated on an inclined ground represented by a normalized normal vector (nx, ny, nz). How can I rotate the car's x and y axes so th ...

What is the reason behind Firefox failing to display a linear gradient when the background-size values are more than 255px?

I am working on creating a grid overlay using an absolutely positioned non-interactive div. My approach involves using the repeating-linear-gradient property as suggested by others for this purpose. The functionality works smoothly in Chrome, but I seem to ...

Exploring new classes with jQuery's .not() and :not()?

I am working on a memory game where I need to flip cards and check if two are equal. My issue is that I do not want the function to run when clicking on a card that is already flipped, or on another flipped card. I tried using jQuery's .not() and :no ...

Retrieve the selected option from the dropdown menu in the specified form

What should I do if I have numerous products and want users to be able to add new dropdown boxes dynamically? When the submit button is clicked, only the value of "category[]" within the form should be retrieved. https://i.stack.imgur.com/v1fnd.png Below ...

Ways to invoke a function within a React Material-UI component

Currently, I am in the process of setting up a chat system that allows users to add emojis. To achieve this feature, I have devised a function that produces a component containing both text and an image. Here is the function I have implemented: test: fu ...

Modify the width of the progress bar in Bootstrap using AngularJS

I'm new to AngularJS and I'm attempting to dynamically update the width of a progress bar based on changes in my controller. Here is what I currently have: <span id="percentage">$ {{getTotal()}} ({{getPercentage()}}%)</span> <div ...

Issue with Google Maps iFrame not loading when utilizing JavaScript variables in the "src" attribute

Currently, I am facing an issue with utilizing JavaScript variables containing GPS latitude and longitude values in the "src" attribute of an iFrame in an HTML file for displaying image EXIF data on a Google Maps iFrame. When I hardcode specific latitude ...

Custom AngularJS directive that permits only alphabetic characters, including uppercase letters and the ability to input spaces

I'm currently working on an AngularJS directive that is meant to only allow alphabetical characters, however, I've encountered an issue where it disables caps lock and space functionality. While the main goal is to prevent special characters and ...

Next.js project encountered a TypeError with message [ERR_INVALID_ARG_TYPE]: The "to" argument is expected to be a string type

While working on a Next.js application, I came across a TypeError that is linked to the undefined "to" argument. This issue pops up when I launch my development server using npm run dev. Despite checking my environment setup and project dependencies, I hav ...

How can you transform a nested array into a flat JavaScript map?

If we consider a JavaScript Map structured like this: [ { id: 1, name: "Foo", contents: [1,2,3], morecontents: ["a","b"], }, { id: 2, name: "Bar", c ...

What could be causing the issue of CSS animation not functioning properly when used in conjunction with a

I am working on creating a switch button with CSS and JavaScript that needs an animation when toggling or clicked. The only issue I am facing is related to the animation. I am wondering if there might be any problem with the positioning (relative, absol ...

What is the best way to ensure that my image completely occupies the div?

I am facing a challenge in creating a hero image that would completely fill the div on my webpage. Despite setting the width and height to 100%, the image seems to only occupy half of the space. Check out the CSS and HTML code snippet here. div.hero{ ...

How to use Javascript to pause an HTML5 video when closed

I am new to coding and currently working on a project in Adobe Edge Animate. I have managed to create a return button that allows users to close out of a video and go back to the main menu. However, I am facing an issue where the video audio continues to p ...

Instructions for resolving the Sys.ArgumentTypeException error: The object of type 'Object' cannot be converted to type 'Function'

I encountered a specific error in my JavaScript function that I'm struggling to resolve. Uncaught Sys.ArgumentTypeException: Sys.ArgumentTypeException: Object of type 'Object' cannot be converted to type 'Function'. Parameter name ...

Content in React Router may fail to load when refreshing the page, navigating forward, or manually

I recently started using React and I'm getting familiar with React Router. I divided my application into two main routes because each uses a different style: the Splash path is for when the user first enters, which contains the Splash screen, Login, a ...

Can you explain the exact meaning of XMLHttpRequest.XMLHttpRequest?

I find MDN's writing style to be confusing. On the MDN page about XMLHttpRequest, it states: XMLHttpRequest is an API ... Constructor XMLHttpRequest.XMLHttpRequest Properties XMLHttpRequest.onreadystatechange XMLHttpRequest.readyState XMLHttpReq ...

Capture data from Ajax requests and store them in PHP variables

When setting up a DDBB Insert using $.ajax, I encountered an issue. $(document).on('click','.submitMessage', function(){ content=$('textarea').val(); img=$('#messageImg').val(); stdMsg=$('.ms_stdMsg ...