Creating a Vue component using v-for and a factory function allows for dynamic

I am currently developing a Table component using factory functions for all logic implementation. Within a v-for loop, I generate a cell for each item in every row.

The factory

Below are the actual factories that I import into the respective vue page where they are needed. Only the relevant code snippets have been included here.

const TableData = (data) => {

        const methods = {
            'getRows': () => {
                const result = []
                for(let i = 0, end = data.length; i < end; i++) {
                    result.push(TableRow(methods, i))
                }
                return result
            }
        }
        return methods
    }


    const TableRow = (parent, rowIndex) => {

        const methods = {
            'getCells': () => {
                const result = []
                for(let colIndex = 0, end = parent.getColumnCount(); colIndex < end; colIndex++) {
                    result.push(TableCell(parent, rowIndex, colIndex))
                }
                return result
            }
        }
        return methods
    }

    const TableCell = (parent, rowIndex, columnIndex) => {

        let active = false

        const methods = {
            'hover': () => {
                active = !active
            },
            'isActive': () => {
                return active
            }
        }
        return methods
    }

The component

Following is the component structure:

<template>
        <div class="table-container">
            <table class="table" v-if="table">
                <thead>
                     <tr>
                        <th class="index-col"></ths>
                        <th v-for="(col, index) in columns">{{col}}</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="row in rows">
                        <td class="cell" v-for="cell in row.getCells()" @mouseenter="cell.hover" @mouseleave="cell.hover" :class="{active: cell.isActive()}">{{cell.getValue()}}</td>
                    </tr>
                </tbody>

            </table>
        </div>
</template>

<script>
import { mapActions, mapGetters } from "vuex";

/* Table Data Factory */
import TableData from "~/plugins/library/table/data_new.js";

export default {
    data() {
        return {
            table: null
        };
    },
    methods: {
        async fetch() {

            /* Fetching data from API - fetchedData is an array */
            this.data = fetchedData

            if(this.data) {
                this.table = TableData(this.data)
            } else {
                console.error('No data available')
            }
        }
    },
    computed: {
        columns() {
            return this.table.getColumns()
        },
        rows() {
            return this.table.getRows()
        }
    },
    mounted() {
        this.fetch()
    }
};
</script>

My objective is to toggle the class when hovering over a cell in the table, changing its active state to true. However, the class property does not observe changes in the cell factory. I have tried various solutions and searched extensively but without success.

I appreciate any assistance or guidance on how to make the class reactive. Thank you in advance!

Answer №1

It appears that the issue lies with this line of code: cell.isActive()

The problem arises from returning a function instead of a reactive variable, which does not indicate any changes. While you could use forceUpdate() to manually trigger an update, it is inefficient as it redraws all cells. It is recommended to avoid using functions for rendering, especially within loops, as they get called on every draw.

An alternative approach would be to have a nested object or array state manage the data for columns, rows, and cells collectively. However, if that does not align with your requirements, consider utilizing a computed property to achieve reactivity without invoking a function. In Vue 2.6+, you can define standalone observables to store and mutate state, generating computed fields as needed.

Similar considerations should be applied to other factories, such as row.getCells(), which regenerates data without maintaining state.

Untested code snippet:

const TableCell = (parent, rowIndex, columnIndex) => {
    const state = Vue.Observable({
        active: false
    });

    const computed= {
        isActive: () => state.active,
    }

    const methods = {
        hover: () => {
            active = !active;
        },
    };
    
    return {...state, ...computed, ...methods};
};

By implementing this structure, you can utilize cell.isActive and ensure reactivity to changes. Furthermore, considering the upcoming Vue 3 release with API composition, component composition will offer additional benefits when working with Vue in this manner.

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

Ajax updates to an element are not reflected until the for loop has completed

I am looking for a way to print a series of numbers sequentially using AJAX. Here is an example of what I want to achieve: (each new line represents an update of the previous line!) Output is: 1 12 123 1234 12345 123456 ... I ...

Guide to pinpointing a location with Google Maps

I am currently working on setting up a contact page that includes Google Maps to show the location of a meeting place. Here is the code I am using: JavaScript (function(){ document.getElementById('map_canvas').style.display="block"; var ...

Is it possible to utilize Jsoup to extract specific portions of JavaScript code from a webpage?

I am looking to extract data from the following script: $(document).ready(function(){ $("#areaName").val(1);$("#state").val(29);$("#city").val(1); $("#subareaName").val(1);$("#lane").val(1); } Specifically, I need to retrieve values such as areaName ...

Incorrect footer navigation on my Vuepress website

I'm in the process of developing a vuepress single page application for showcasing and providing downloads of my personal game projects. When it comes to website navigation, I am aiming to utilize the native sidebar exclusively. This sidebar will hav ...

Using Node.js and the Jade templating engine, display the value of a passed variable

Asking such a basic question makes me feel guilty. app.get('/skumanagement/:id', function (req, res){ var options = req.params.id; // req.params.id = itemidx database.skuGetDetail(options, function (error, data){ winston.log('inf ...

Ongoing backend polling in vuejs is experiencing delays

In my Vue component, I have a conditional rendering setup where different components are displayed based on the GET response. Here is a simplified version: data() { return { responseStatus: null, // Variable for conditional rendering respons ...

Close the overlay by clicking outside of it

I'm working on creating a unique pop-up window that appears when a customer adds a product to their cart. The design features red and green background divs with a darker overlay (#overlay-daddy) and a white child div (#overlay). My issue arises from ...

Value in Vue does not update when binded to input field

With the code below, the expectation is that when a minus sign is inputted, vue will replace the negative value with a positive one. <input type="number" :value="localValue" @input="$event => { onInput($event.target. ...

JavaScript Error Caused by Newline Characters

I'm facing an issue with extracting data from a textbox using JavaScript. What I'm attempting to do is retrieve the value from a textbox, display it in an alert, and then copy it. Here's the current code snippet: var copyString = "Date: < ...

Can you explain how to retrieve the header value from ng-table?

Is there a way to retrieve the table header for each column from JavaScript? When I call tableTest, it only returns data of each row, not the header names like 'name' and 'description'. Is there a method like tableTest.data-title to acc ...

Turn off Chrome 69's autofill functionality

I've recently encountered an issue with Chrome's password autofill feature that has been troubling me for a few days now. This problem began when I was using Chrome version 69. After much trial and error, I found a solution by removing the id an ...

Encountering an error while running npm install in a forked VueJS application

Recently, I was tasked by a company to develop a simple Vue app. To get started, I forked the code from their repository and attempted to run npm install. Unfortunately, this process resulted in several errors as detailed in this log file. Additionally, he ...

Position a div element after another using the :after pseudo-element

My goal is simple to explain, but I have exhausted all my efforts trying to achieve it. I am hoping for the ★ symbol to appear immediately after the number 06 using jQuery. Any assistance would be greatly appreciated. The numbers are generated by a s ...

Having trouble publishing project on Vercel because of a naming issue

Whenever I try to deploy a project on vercel, I encounter an error stating that the project name is not valid. The specific error messages are as follows: Error: The name of a Project can only contain up to 100 alphanumeric lowercase characters and hyphe ...

Can I find a better approach to optimize this code?

How can I refactor this code to move the entire DB query logic into a separate file and only call the function in this current file? passport.use( new GoogleStrategy({ clientID: googleId, clientSecret: clientSecret, callbackURL: ...

Display an icon before an active v-list-item in Vuetify 3's v-list

I need help figuring out how to add an icon to a v-list-item only if it is active. <v-list class="px-15 pt-5" border density="compact"> <v-list-item v-for="(item,i) in items"> <!-- Need assistance putting ...

Tips for concealing the URL in the address bar while using `<a href>` links

I have a variety of documents saved in a folder within an ASP MVC 5 project. Instead of directly linking to the document with an HTML tag, I am utilizing the following ng-href: <a ng-href="~/download/document/{{vm.document}}"></a> By using th ...

Navigating through a mergeMap observable with an undefined value

In my Angular 6 app, I have a class that attaches API tokens to every http request using the getIdToken() method. If the token retrieval is successful, everything works fine. However, if it fails, my app will stop functioning. I need help with handling th ...

Spontaneously generating models

Explaining this concept can be a bit complex. I am tasked with creating an object that contains properties from dynamic HTML code. To illustrate, let's use an example: Firstly, here is my data object: var myObject = {Field1: 'Value1', Fiel ...

Performing an RxJS loop to retrieve the httpGet response, followed by executing httpPut and httpPost requests based

I am currently working on a UI form that allows users to update or add translation text. To achieve this, I need to create an rxjs statement that will perform the following tasks: Send an httpGet request to the database to retrieve translations in mult ...