Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

loced35156's avatar

Reusable component in vue js with dynamic fields

Hello, i am working on a project with vue js and laravel. Until now i have hard code my project and i think its time to work with reusable component. I am trying to do something with a section witch is on top of my table. I mean i have a table where i fetch data and on top of table are some button with custom action like add record, filter, etc I want this button to be same on other tables but foreach table is another modal (EX: User table have a add user modal , Role table have add role modal with other fields). I hope was clear and anyone will understand.I am posting some code

customAction.js

import Modal from './modal.js';
import Button from './button.js';

export default {
    components: {
        'v-modal' : Modal,
        'v-button': Button
    },

    data() {
        return {
            editModalVisibility: false,
            addModalVisibility: false,
            selected: [],
            id: '',
            user_id: '',
            password: '',
            name: '',
            email: '',
            query: '',
            url: ''
        }
    },

    methods: {
        addUser(){
            this.$emit('addUser', this.user_id, this.name, this.email, this.password)
        },
    },

    template: `
        <div class="add-user py-4">
            <div class="d-flex">
                <div class="col-10">
                    <!-- Button trigger modal -->
                    <v-button type="success" @click.prevent="addModalVisibility = !addModalVisibility" >
                        Add User
                    </v-button>
                    <v-button type="primary" data-mdb-toggle="collapse" data-mdb-target="#collapseFilter" aria-expanded="false" aria-controls="collapseFilter" >
                        Filter
                        <i class="fa-solid fa-filter"></i>
                    </v-button>
                    <v-button v-show="selected.length>0" type="danger" class="dropdown dropdown-toggle" id="dropdownMenuButton" data-mdb-toggle="dropdown" aria-expanded="false" >
                            Action ({{selected.length}})
                    </v-button>
                    <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
                        <li>
                            <a :href="url" class="dropdown-item btn-warning text-center">
                                Export
                                <i class="fa-solid fa-file-excel"></i>
                            </a>
                        </li>
                        <li>
                            <v-button @click="massDeleteUser()" type="danger" class="dropdown-item text-center">
                                Delete
                                <i class="fa-solid fa-trash"></i>
                            </v-button>
                        </li>
                    </ul>
                </div>
                <div class="col-2">
                    <input v-model="query" type="search" class="form-control border-0" placeholder="Search" />
                </div>
            </div>

            <!-- Add Modal -->
            <v-modal v-model="addModalVisibility" @submit_changers="addUser">
                <template v-slot:modalTitle>
                    Add User
                </template>
                <form id="" class="form-horizontal validate-form">
                    <div class="form-group mb-2">                
                        <input v-model="user_id" id="user_id" type="number" class="form-control" placeholder="user_id">        
                    </div>          
                    <div class="form-group mb-2">                
                        <input v-model="name" id="name" type="text" class="form-control" placeholder="name">        
                    </div>          
                    <div class="form-group mb-2">                
                        <input v-model="email" id="email" type="email" class="form-control" placeholder="email">        
                    </div>          
                    <div class="form-group mb-2">                
                        <input v-model="password" id="password" type="password" class="form-control" placeholder="password">        
                    </div>
                </form>
                <template v-slot:modalFooterBtn>
                    Save
                </template>
            </v-modal>
            
        </div>
    `,
}

userComponent

<v-action @addUser="addUser"></v-action>

import customAction from './partials/customAction.js';
 export default {
        components: {
            'v-action': customAction,
        },

methods: {
addUser(user_id, name, email, password){
                axios({
                    method: 'POST',
                    url: '/admin/users',
                    data: {
                        user_id: user_id,
                        name: name,
                        email: email,
                        password: password
                    }
                })
                .then(response => {
                    this.addModalVisibility = !this.addModalVisibility //also i need to pass this value on customAction.js to close the modal after success
                    this.getUsers()
                    Toastify({
                        text: response.data.success,
                        className: "info",
                        duration: 3000,
                        position: "right",
                        gravity: "top",
                        close: true,
                        stopOnFocus: true,
                        style: {
                            background: "#3a3b3c"
                        }
                    }).showToast();
                })
                .catch(error => {
                    // console.log(error.response.data.errors.password);
                    Toastify({
                        text:  error.response.data.message,
                        className: "info",
                        duration: 3000,
                        position: "right",
                        gravity: "top",
                        close: true,
                        stopOnFocus: true,
                        style: {
                            background: "#3a3b3c"
                        }
                    }).showToast();
                });
            },

}

0 likes
0 replies

Please or to participate in this conversation.