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

Leveraging an external script for enhanced functionality in React/Meteor application

I'm currently facing a challenge incorporating an external script into my React component within Meteor. I've experimented with directly placing the script tag in my component as follows: TheLounge = React.createClass({ render() { return ( ...

What is the solution to rectifying the issue with graphql codegen?

Upon running the command "yarn graphql-codegen," an error occurred and I am unsure how to resolve it: % yarn graphql-codegen yarn run v1.22.4 warning package.json: No license field $ /Users/xxx/node_modules/.bin/graphql-codegen ✔ Parse Configuration ⚠ ...

MongoSearch: A Geo-Targeted Search Engine tailored to your needs

For my new app project, I am using MongoDB, Express, JS, and Node to create a platform similar to Yelp. After some research, I discovered how to search for multiple fields within a campus schema (including campuses, restaurants, barbershops, and names). No ...

Navigating between socket.io and express using while loops

Currently, I am running an express app with socket.io on my raspberry pi to control an LED panel. The panel is being driven by a while loop that updates the pixels. However, I am looking for a way to modify the parameters of this loop or even switch to a d ...

Resolving unexpected behavior with res.locals and pug integration

I have a function in my app.js that allows the user-id to be accessible in pug templates. app.use(function (req, res, next) { res.locals.currentUser = req.session.userId; next(); }); When logged in, I can access the id. However, when not logged in, t ...

Exploring the possibilities with Vue 3, Vite, and ZoomSDK

I am encountering difficulties while integrating the Zoom Meetings SDK with Vue 3 and Vite. This is a basic setup of a Vue 3 project using the Vue-create CLI. I have also registered my app with Zoom and obtained my SDK key and SDK secret. Following the i ...

Exploring the world of nested routes in Angular and how to efficiently

Hey there! I'm brand new to all of this and still trying to wrap my head around a few things, so any guidance you can offer would be awesome! :) Overview I've got a bunch of projects (/projects) Clicking on a project takes me to a detailed sum ...

Adjusting the width of a div element using a button

I am currently diving into the world of JavaScript, React, and Node.js. My current challenge involves attempting to adjust the width of a div element using a button. However, I keep encountering the same frustrating error message stating "Cannot read prope ...

Navigating Dynamically between tabs - A How-to Guide

I am working on a mat-tab Angular app where I need to dynamically generate links and transfer them to a navLinks object. Despite ensuring that the concatenation is correct, it seems like my approach is not working as expected. Here's a glimpse of what ...

How to send arguments to a callback function in Next.JS

Here's the code snippet I'm working with: import Router from "next/router"; import React from "react"; export default function MainIndex() { return (<React.Fragment> <h1>Main Index Page</h1> ...

No styles are appearing on a specific element after running a specific jQuery function on that element within a Vue page

I recently integrated JQuery-AsRange (https://github.com/thecreation/jquery-asRange) into my vue.js project. Everything functions as expected within the .vue page, however, I am facing an issue with css styling not being applied. The css styles should be ...

What results can be expected from a piped file stream?

Perhaps the wording of the question may not be perfect, but here is some additional context. With GridFSBucket, I am able to store a file in MongoDB and retrieve a download stream for that file. Here's my query: If I wanted to send that file back as a ...

Dragging elements with jQueryUI multiple times

Is there a way to configure drag and drop functionality so that one element can be dragged multiple times? I attempted to create something similar to this http://jsfiddle.net/28SMv/3/, but after dragging an item from red to blue, the element loses its abi ...

Generate Array of Consecutive Dates using JavaScript

My array contains the following values (for example): [ 1367848800000: true, 1367935200000: true, 1368021600000: true, 1368108000000: true, 1368194400000: true, 1368367200000: true, 1368540000000: true, 1 ...

Get started by setting up and utilizing react version 0.14.0 on your

I'm currently facing an issue in my project while using react-0.14.0. The error message I'm encountering is: Invariant Violation: ReactDOM.render(): Invalid component element. This may be caused by unintentionally loading two independent copie ...

The build process encounters an issue with initializing Sentry's Vuejs (with Typescript) Integration

While attempting to build my (vue-cli-3 based) Vuejs project using gitlab-runner on my local machine, an error occurs: 98% after emitting CopyPlugin ERROR Failed to compile with 1 errors ... Property 'util' is missing in type 'VueConstruct ...

I can't understand why this question continues to linger, I just want to remove it

Is there a valid reason for this question to persist? I'm considering removing it. ...

What could be causing my for loop to not function properly within the ngOnInit lifecycle hook?

I am attempting to create a nested loop structure in order to access an array that is inside an object within an array of objects, and then store this data into a new array. My issue arises as the first loop executes successfully but the second one does no ...

The hover functionality fails to activate when a z-index is applied

My issue revolves around 2 divs: one containing a link and the other a box-shaped container. The link is set with position:fixed; causing it to fly over the container div. To resolve this, I attempted to assign a negative z-index value to the link, but unf ...

The absence of req.body in the app reflects an undefined state

I'm encountering an issue with my app and I believe showing you my code is the best way to explain the problem: var Meetup = require('./models/meetup'); module.exports.create = function (req, res) { var meetup = new Meetup(req.body); c ...