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

Maison012's avatar

Toggle each element in array does not work

I have a table in vue js which I fill with data from the backend. I copy the entire db structure as an object and display it in vue js as it is with all the fields. Now I'm stuck somewhere, more precisely I want to have a management of the fields of the table by deciding whether I want to display or not in the table. I made a function that works but not as expected, can someone help me to develop it properly?

<button class="btn btn-info dropdown dropdown-toggle" type="button" id="setVisibility" data-mdb-toggle="dropdown" aria-expanded="false" >
   TABLE FIELD MENAGMENT 
</button>
  <ul class="dropdown-menu prevent-close py-1 px-2" aria-labelledby="setVisibility">
    <li>
     <div class="layout-header pt-2 text-center">
     <h6>Hide/Show</h6>
     </div>
     <div v-for="(header, key, index) in visibleHeaders" :key="key" class="form-check form-switch">
       <input v-model="isHidden" :value="key" class="form-check-input " type="checkbox" id="isHidden">
       <label class="form-check-label" for="isHidden">{{header}}</label>
     </div>
    </li>
  </ul>

<thead class="">
<tr>
   <th><input type="checkbox" class="form-check-input" v-model="selectAll" title="Select All"></th>
   <th v-if="!isHidden" v-for="(header, index) in visibleHeaders" :key="index" scope="col">
       {{ header }}
   </th>
   <th>ACTION</th>
</tr>
</thead>

...

data() {
   return {
     isHidden: false,
     headers: [],
     ...
    }
}
 computed: {
        visibleHeaders() {
            return this.headers.map(h => {
                h.isHidden = true
                return h.Field.replace("_", " ").toUpperCase()
            });
        },
}

0 likes
5 replies
lbecket's avatar

You have a number of issues. To start, you are determining visibility based on the data element isHidden, which you have initialized as false and there's nothing in this code that changes it. I suspect that you are trying to change it in the computed property visibleHeaders, but that's not how computed properties work; the computed property returns a different object with isHidden as a property on that object, so you're referencing something different. Furthermore, you don't want to use v-if on your v-for loop. Instead, you should use the computed property to filter for the desired elements and iterate on that. Even so, based on your other recent posts as well as what you've indicated here, the filtering should be happening on the back end and so there should not even be a need for a computed property. I also don't see a method to toggle visibility... I assume that's setVisibility but you haven't shared that code.

Like I said, you have a number of issues. As I had indicated here, manage the data structure on the back end and allow the vue component to consume it based on the data it receives. There's no need to apply any filtering on the front end if your data is structured to meet the need on the back end.

Maison012's avatar

@lbecket I really appreciate your help and your answers, this is my first time doing something like this and I don't know how to manage this data from the backend. That's why I was trying to do it from the front end because this would be a very easy function if everything was written as hard code, I mean if I had set the static fields.

I tried to add an option in computed that changes `isHidden = false or ture' but without the results I expected. So if you can please help me to do this correctly?

I am removing from the v-if code that I have placed together with v-for, while in the backend I have the function that you advised me from the other therad

note: I cant use this method

$queryResults = Lead::select('field_1', 'field_2')->get();

beacouse i dont know what field i have on db, they change sometime , this is the reason i am trying to do this thing on frontend

lbecket's avatar

@Leon012 No worries; this can definitely be confusing initially. Below is a vue component and a controller that will get this working for you. You'll obviously have to modify the query if you don't have a Lead model or if you require additional filters, but this should get you started. Also note that you need to define a fields object in your component with an initial state for the visibility of each field. I included an alias property in case the database field name is not what you want to display in the table header.

Vue.js

<template>	
	<div>
		<button 
			class="btn btn-info dropdown dropdown-toggle" 
			type="button" 
			id="setVisibility" 
			data-mdb-toggle="dropdown" 
			aria-expanded="false" 
		>
   			TABLE FIELD MANAGEMENT 
		</button>

		<ul 
			class="dropdown-menu prevent-close py-1 px-2" 
			aria-labelledby="setVisibility"
		>
			<li>
				<div class="layout-header pt-2 text-center">
					<h6>Hide/Show</h6>
				</div>

				<div 
					v-for="(field, i) in fields" 
					:key="i" 
					class="form-check form-switch"
				>
					<input 
						v-model="field.visible"
						class="form-check-input" 
						type="checkbox" 
						id="isHidden"
						@change="getData()"
					>
					<label 
						class="form-check-label" 
						for="isHidden"
					>
						{{ field.name }}
					</label>
				</div>
			</li>
		</ul>

		<table>
			<tr>
				<th 
					v-for="(header, i) in headers" 
					:key="i" 
					scope="col"
				>
					{{ header }}
				</th>
			</tr>

			<tr
				v-for="(lead, i) in leads"
				:key="i"
			>
				<td
					v-for="(field, j) in lead"
					:key="j"
				>
					{{ field }}
				</td>
			</tr>
		</table>


	</div>
</template>

<script>
	export default{
		data() {
			return {
				leads: [],
				headers: [],
				fields: [
					{name: 'first_name', alias: 'First Name', visible: true},
					{name: 'last_name', alias: 'Last Name', visible: true},
					{name: 'email', alias: 'Email', visible: false},
				]
			}
		},

		methods: {
			getData() {
				axios.post('/getLeads', {fields: this.fields}).then(response => {
					this.leads = response.data;

					this.headers = this.fields.map(item => {
						if (item.visible) {
							return item.alias;
						}
					});

				});
			},
		},

		mounted() {
			this.getData();
		}
	}
</script>

SomeController.php

public function getLeads(Request $request)
    {
        $fields = collect($request->fields)
            ->where('visible', true)
            ->pluck('name')
            ->implode(',');
            
        if ($fields != "") {
            return Lead::selectRaw($fields)->get();
        }

        return [];
    }
Maison012's avatar

@lbecket I tryed this method and i see it works.

you need to define a fields object in your component with an initial state for the visibility of each field

But as i told you i really dont know what field are on table beacouse they need to change, I dont want to hard code each field.

FOR EXAMPLE

In a db.table i know i have a first name last name and email and if i use this code manually it works

fields: [
                {name: 'first_name', alias: 'First Name', visible: true},
                {name: 'last_name', alias: 'Last Name', visible: true},
                {name: 'email', alias: 'Email', visible: false},
            ],

But what if i have a form on view where i can add new field on this table. Then the field i will created will not added on fields[] array. Or in case i will clone a table from another db2.table, maybe there is a way to fill the fields dynamically?

Maison012's avatar

I found another way to do this function.

// first add [index] on `v-modal`
<button class="btn btn-info dropdown dropdown-toggle" type="button" id="setVisibility" data-mdb-toggle="dropdown" aria-expanded="false" >
                            Layout
                        </button>
                        <ul class="dropdown-menu prevent-close py-1 px-2" aria-labelledby="setVisibility">
                            <li>
                                <div class="layout-header pt-2 text-center">
                                    <h6>Hide/Show</h6>
                                </div>
                                <div v-for="(header, index) in visibleHeaders" :key="index" class="form-check form-switch">
                                    <input v-model="isHidden[index]" :value="index" class="form-check-input " type="checkbox" id="isHidden" >
                                    <label class="form-check-label" for="isHidden">{{header}}</label>
                                </div>
                            </li>
                        </ul>
//also on table `v-if` add `[index]` after `isHidden` method
<table class="table table-hover align-middle mb-0">
                    <thead class="">
                        <tr>
                            <th><input type="checkbox" class="form-check-input" v-model="selectAll" title="Select All"></th>
                            <th v-if="!isHidden[index]" v-for="(header, index) in visibleHeaders" :key="index" scope="col">
                                {{ header }}
                            </th>
                            <th>ACTION</th>
                        </tr>
                    </thead>
                    <!-- Collapsed content ./ -->
                    
                    <!-- ./ Collapse contet -->
                    <tbody>
                        <tr v-show="leads.length" v-for="column in leads" >
                            <td>
                                <input type="checkbox" class="form-check-input" v-model="selected" :value="column.id" />
                            </td>
                            <td  v-if="!isHidden[index]" v-for="(atr, key, index) in column">
                                {{ atr }}
                            </td>
                            <td>
                                <a @click="showLead(column.id)" class="btn btn-sm btn-info" data-mdb-toggle="modal" data-mdb-target="#editLeadModal">
                                    <i class="fa-solid fa-eye"></i>
                                </a>
                                <button @click="editLead(column.id)" type="button" class="btn  btn-sm btn-secondary"  data-mdb-toggle="modal" data-mdb-target="#editLeadModal" >
                                    <i class="fa-solid fa-pen-to-square"></i>
                                </button>
                            </td>
                        </tr>
                        <tr v-show="!leads.length">
                            <td colspan="12" class="text-center">Sorry :( No data found.</td>
                        </tr>
                    </tbody>
                </table>

and define isHidden: [], ass array in component data()

Please or to participate in this conversation.