What is the best approach to developing Vue components with unique templates while maintaining the same functionality without duplicating code?

I am working on a project to develop a custom and versatile datatable component. My goal is to be able to adjust the appearance of the datatable on each page, while maintaining consistent functionality. I want to pass data rows into the component and have the flexibility to customize the layout accordingly. However, I am struggling to figure out how to achieve this. Here's an illustration of my dilemma:

For instance, one page may require this template:

<datatable>
    <div v-for="row in rows" class="header" @click="sortBy(row.field)">row.title</div>
    <div v-for="row in rows">row.value</div>
</datatable>

While another page demands a different layout:

<datatable>
    <h1>
        <span v-for="row in rows" @click="sortBy(row.field)">row.title</span>
    </h1>

    <h3 v-for="row in rows">row.value</h3>
</datatable>

I am grappling with a solution to integrate the sortBy function inside the component. Is there a way to make this work seamlessly?

Answer №1

1. Building a New Component

Component Location: ./src/components/dataTableComponent.vue

<template>
    <datatable>

        <div v-if="!withTitles">
            <div v-for="(row, index) in rows" :key="index" class="header" @click="sortBy(row.field)">row.title</div>
            <div v-for="(row, index) in rows" :key="index">row.value</div>
        </div>

        <div v-id="withTitles">
            <h1>
                <span v-for="(row, index) in rows" :key="index" @click="sortBy(row.field)">row.title</span>
            </h1>
            <h3 v-for="(row, index) in rows" :key="index">row.value</h3>
        </div>

    </datatable>
</template>
<script>
export default {
    name: 'dataTableComponent',
    props: ['rows', 'withTitles'],
    data () {
        return {

        }
    },
    methods: {
        sortBy(field){
            //Sorting logic for this.rows
        }
    }
}
</script>

2. Implementing the Component

<template>
    <div>

        <h2>No Titles</h2>
        <dataTableComponent :rows="rows" :withTitles="true">
        
        <h2>With Titles</h2>
        <dataTableComponent :rows="rows">

    </div>
</template>
<script>
import dataTableComponent from 'src/components/dataTableComponent.vue';

export default {
    components: {dataTableComponent},
    data () {
        return {
            rows: ['AAA', 'BBB', 'CCC']
        }
    }
}
</script>

Explore Vue Documentation for Additional Options

Answer №2

One useful tool in Vue is the slot feature, which allows you to customize components. Check out more information about slots here.

datatable.vue

<template>
  <div>
    <slot name="table-slot"></slot>
  </div>
</template>

<script>
  export default {
    name: 'datatable'
  }
</script>

sampleComp1.vue

<template>
  <div>
    <datatable>
        <div slot="table-slot">
            // include your template data here
        </div>
    </datatable>
  </div>
 </template>

 <script>
   import datatable from './datatable.vue';

   export default {
     name: 'sampleComp1',
     data() {
        rows: [] // populate this array with your data
     },
     components: {
        datatable
     },
     methods: {
        sortBy(field) {
            // perform necessary actions here
        }
        
     }
   }
</script>

sampleComp2.vue

<template>
  <div>
    <datatable>
        <div slot="table-slot">
            // include your template data here
        </div>
    </datatable>
  </div>
 </template>

<script>
  import datatable from './datatable.vue';

  export default {
    name: 'sampleComp2',
    data() {
        rows: [] // populate this array with your data
    },
    components: {
        datatable
    },
    methods: {
        sortBy(field) {
            // perform necessary actions here
        }
    }
  }
 </script>

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

Click on a specific image in a table using Cypress with a specific source URL

I need help with a query for Cypress regarding a table of items, each item having active (blue) and not active (black) images. How can I set up this query? Below is an image of the table list: https://i.stack.imgur.com/74qzb.png And here is the HTML code ...

Enable a click event within an iFrame by clicking on an element in the parent document

I am attempting to trigger the click event of an element inside an iFrame (specifically a standard Twitter follow button) when clicking on an element within my main webpage. Below is the code snippet I have been experimenting with, but unfortunately it do ...

Is there a way to show a 'Refresh' icon in HTML without the need to download an image through HTTP?

In my HTML/JavaScript app project, I am looking to incorporate a 'refresh' symbol without having to load an image through HTTP requests. Are there reliable methods that can achieve this across all major browsers? I came across the Unicode value: ...

Permanently dismiss Bootstrap 4 alert using a cookie

Recently, I came across a bootstrap 4 alert that I found quite useful. Here is the code snippet for it: <div class="alert alert-warning alert-dismissible fade show" role="alert"> <button type="button" class="clo ...

What could be the reason behind my Javascript code returning "object object"?

I am a beginner with jQuery. I attempted to calculate the sum of items from my django views using jQuery. Here's what I have so far: $(document).ready(function() { var sch = $('#sch-books'); var gov = $('#gov-books'); ...

How to maximize efficiency by utilizing a single function to handle multiple properties in Angular

I have 2 distinct variables: $scope.totalPendingDisplayed = 15; $scope.totalResolvedDisplayed = 15; Each of these variables is connected to different elements using ng-repeat (used for limitTo) When the "Load More" button is clicked (ng-click="loadMore( ...

Error encountered with CORS in a Socket.io Express HTTP server backend

While developing an app that utilizes express for the backend, I decided to incorporate socket.io for real-time chat functionality. Everything was working flawlessly on postman until my front end react code triggered a cors error when making a GET request ...

Stylus Vue Vite: The Trio of Global Variables

I'm trying to figure out how to globally import and use stylus variables in my Vue Vite project. How can I achieve this and access the variables within the script section of my Single File Component (SFC)? Below is an excerpt from my Vite config: exp ...

Encountering 404 errors in production when using vue-router with Node.js for URL paths

While trying to deploy a multipage vue3 frontend to an application, everything seems to work fine in development mode. However, when I switch to production and attempt to navigate to a specific URL through the search bar - like , I encounter a 404 error. ...

Words program with the header feature incorporated

Hello, I am currently working with Laravel to build an HTML page and have successfully converted it to MS Word. However, I am now trying to add a header inside. Can anyone help me achieve this? Here is a snippet of my code: <body> <a class= ...

The node experiences a crash when the redis-server goes offline

Struggling with a persistent issue here. Despite reading numerous documents and posts from others on the same topic, I can't seem to find a solution to prevent this problem. I am intentionally shutting down the redis server to avoid potential disaster ...

Utilizing the require pattern to integrate JavaScript functionality into HTML

Have: project |- consume_script.js |- index.html Need index.html to be like: <html> <head> </head> <body> <script src="consume_script.js"></script> </body> </html> Issue: consume_script ...

Combining two numbers retrieved from Firebase using React

Hello, I am new to React and finding it challenging to perform mathematical calculations with React. I have been attempting to add two values retrieved from a Firebase database, but they keep displaying as strings without adding the actual values together. ...

The RxDB Angular2-cli error message. "Cannot assign a 'Promise<void>' to a 'Promise<any>' parameter."

I've been grappling with getting RxDB to function properly in a fresh project I initiated using the Angular CLI. Here's my process: ng new <Projectname> After that, I installed RxDB by running: npm install rxdb Following the example p ...

How to apply multiple filters in JavaScript?

I have a set of objects that require filtering. If the object has an active status of true, it should always be included in the filtered result regardless of other conditions. If there is text entered for search, then the remaining items should be filter ...

Automated configuration of AWS Amplify JavaScript using Gitpod

Looking to streamline the setup process for an AWS Amplify JavaScript project on Gitpod. My goal is to eliminate the manual steps of configuring the amplify-cli, such as adding IAM users and generating the aws-exports.js file. Successfully installed the a ...

Preventing Vue.js from triggering watch on initial load

I need to implement a feature where a button is initially disabled and only becomes enabled when the input value is changed. To achieve this, I am using a boolean flag that is set to true by default and turns false only when the input changes. The v-model ...

Ways to Press the Enter Key on Different Browsers

Looking for a solution to get the keypress action working properly? I have a chat feature where I need to send messages. Here is what I have in the Form-tag (JSP based): function SendMessage() { if (event.keyCode===13) { ale ...

Changing a date string to MM DD format in React without using plain JavaScript

I'm familiar with how to handle this outside of React. My issue is that I have a date string coming from an API within an object, and I need to reformat it. The current format is "2022-12-13T06:00Z" but I want it to display as "December 13". The objec ...

Angular is not programmed to automatically reflect updates made to my string array

let signalRServerEndPoint = 'https://localhost:44338'; this.connection = $.hubConnection(signalRServerEndPoint); this.proxy = this.connection.createHubProxy('MessagesHub'); this.proxy.on("ReceiveMessage", (message) => { ...