Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/7span/vue-list/llms.txt

Use this file to discover all available pages before exploring further.

The <VueListAttributes> component provides UI controls for showing/hiding columns in a table or attributes in a list. It’s useful for letting users customize which fields they want to see.

Basic usage

<template>
  <VueList endpoint="users" :attrs="['name', 'email', 'role', 'created_at']">
    <VueListAttributes />
    
    <VueListItems #default="{ items }">
      <div v-for="user in items" :key="user.id">
        {{ user.name }} - {{ user.email }}
      </div>
    </VueListItems>
  </VueList>
</template>

Props

This component has no props. It uses Vue’s inject to access the list state from the parent <VueList> component.
Important: You must pass the attrs prop to the <VueList> component to define which attributes are available.

Slot

The default slot receives a scope object:
<VueListAttributes #default="{ attrs, settings, update }">
  <div class="attribute-controls">
    <label v-for="attr in attrs" :key="attr.name">
      <input
        type="checkbox"
        :checked="settings?.[attr.name]?.visible"
        @change="update(attr.name, 'visible', $event.target.checked)"
      />
      {{ attr.label }}
    </label>
  </div>
</VueListAttributes>

Scope object

  • attrs - Array of attribute objects with name and label
  • settings - Current settings object (e.g., { name: { visible: true }, email: { visible: false } })
  • update(name, prop, value) - Function to update an attribute’s settings

Examples

Checkbox list

<VueListAttributes #default="{ attrs, settings, update }">
  <div class="space-y-2">
    <p class="text-sm font-medium text-gray-700">Show columns:</p>
    <label
      v-for="attr in attrs"
      :key="attr.name"
      class="flex items-center gap-2 cursor-pointer"
    >
      <input
        type="checkbox"
        :checked="settings?.[attr.name]?.visible"
        @change="update(attr.name, 'visible', $event.target.checked)"
        class="rounded"
      />
      <span class="text-sm">{{ attr.label }}</span>
    </label>
  </div>
</VueListAttributes>
<VueListAttributes #default="{ attrs, settings, update }">
  <div class="relative">
    <button @click="showMenu = !showMenu" class="btn-secondary">
      Columns
      <svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor">
        <path d="M19 9l-7 7-7-7" />
      </svg>
    </button>
    
    <div v-if="showMenu" class="absolute right-0 mt-2 bg-white shadow-lg rounded-lg p-4 z-10">
      <label
        v-for="attr in attrs"
        :key="attr.name"
        class="flex items-center gap-2 py-1"
      >
        <input
          type="checkbox"
          :checked="settings?.[attr.name]?.visible"
          @change="update(attr.name, 'visible', $event.target.checked)"
        />
        <span>{{ attr.label }}</span>
      </label>
    </div>
  </div>
</VueListAttributes>

<script setup>
import { ref } from 'vue'
const showMenu = ref(false)
</script>

With select all / deselect all

<VueListAttributes #default="{ attrs, settings, update }">
  <div class="column-selector">
    <div class="flex items-center justify-between mb-3">
      <p class="font-medium">Columns</p>
      <div class="flex gap-2">
        <button @click="selectAll(attrs, update)" class="text-xs text-blue-600">
          Select All
        </button>
        <button @click="deselectAll(attrs, update)" class="text-xs text-gray-600">
          Clear
        </button>
      </div>
    </div>
    
    <div class="space-y-2">
      <label v-for="attr in attrs" :key="attr.name" class="flex items-center gap-2">
        <input
          type="checkbox"
          :checked="settings?.[attr.name]?.visible"
          @change="update(attr.name, 'visible', $event.target.checked)"
        />
        <span>{{ attr.label }}</span>
      </label>
    </div>
  </div>
</VueListAttributes>

<script setup>
function selectAll(attrs, update) {
  attrs.forEach(attr => update(attr.name, 'visible', true))
}

function deselectAll(attrs, update) {
  attrs.forEach(attr => update(attr.name, 'visible', false))
}
</script>

Using with table

<template>
  <VueList endpoint="users" :attrs="columns">
    <div class="mb-4">
      <VueListAttributes #default="{ attrs, settings, update }">
        <div class="flex gap-2">
          <label v-for="attr in attrs" :key="attr.name" class="inline-flex items-center gap-1">
            <input
              type="checkbox"
              :checked="settings?.[attr.name]?.visible"
              @change="update(attr.name, 'visible', $event.target.checked)"
            />
            <span class="text-sm">{{ attr.label }}</span>
          </label>
        </div>
      </VueListAttributes>
    </div>
    
    <table class="w-full">
      <thead>
        <tr>
          <th v-if="isVisible('name')">Name</th>
          <th v-if="isVisible('email')">Email</th>
          <th v-if="isVisible('role')">Role</th>
          <th v-if="isVisible('created_at')">Created</th>
        </tr>
      </thead>
      <tbody>
        <VueListItems #default="{ items }">
          <tr v-for="user in items" :key="user.id">
            <td v-if="isVisible('name')">{{ user.name }}</td>
            <td v-if="isVisible('email')">{{ user.email }}</td>
            <td v-if="isVisible('role')">{{ user.role }}</td>
            <td v-if="isVisible('created_at')">{{ user.created_at }}</td>
          </tr>
        </VueListItems>
      </tbody>
    </table>
  </VueList>
</template>

<script setup>
import { inject } from 'vue'

const columns = [
  { name: 'name', label: 'Name' },
  { name: 'email', label: 'Email' },
  { name: 'role', label: 'Role' },
  { name: 'created_at', label: 'Created At' }
]

const attrSettings = inject('attrSettings')

function isVisible(attrName) {
  return attrSettings.value?.[attrName]?.visible !== false
}
</script>

Popover style

<VueListAttributes #default="{ attrs, settings, update }">
  <div class="relative">
    <button
      @click="showPopover = !showPopover"
      class="flex items-center gap-2 px-3 py-2 border rounded hover:bg-gray-50"
    >
      <svg class="w-4 h-4" fill="none" stroke="currentColor">
        <path d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
      </svg>
      <span class="text-sm">Customize Columns</span>
    </button>
    
    <div
      v-if="showPopover"
      class="absolute right-0 mt-2 w-64 bg-white border rounded-lg shadow-xl p-4 z-20"
    >
      <h3 class="font-medium mb-3">Show/Hide Columns</h3>
      
      <div class="space-y-2 max-h-64 overflow-y-auto">
        <label
          v-for="attr in attrs"
          :key="attr.name"
          class="flex items-center gap-2 p-2 hover:bg-gray-50 rounded cursor-pointer"
        >
          <input
            type="checkbox"
            :checked="settings?.[attr.name]?.visible"
            @change="update(attr.name, 'visible', $event.target.checked)"
            class="rounded"
          />
          <span class="text-sm">{{ attr.label }}</span>
        </label>
      </div>
    </div>
  </div>
</VueListAttributes>

<script setup>
import { ref } from 'vue'
const showPopover = ref(false)
</script>

Accessing visibility state

You can check if an attribute is visible using the injected attrSettings:
<script setup>
import { inject, computed } from 'vue'

const attrSettings = inject('attrSettings')

const isNameVisible = computed(() => {
  return attrSettings.value?.name?.visible !== false
})
</script>

State persistence

Attribute visibility is automatically persisted via the stateManager if configured. When users return, their column preferences are restored.
app.use(VueList, {
  requestHandler(context) {
    // ... your request handler
  },
  stateManager: {
    init(context) {
      // Initialize state
    },
    get(context) {
      const key = `vuelist-${context.endpoint}-${context.version}`
      const state = localStorage.getItem(key)
      return state ? JSON.parse(state) : null
    },
    set(context) {
      const key = `vuelist-${context.endpoint}-${context.version}`
      const state = {
        attrSettings: context.attrSettings, // Column visibility saved here
        page: context.page,
        perPage: context.perPage
      }
      localStorage.setItem(key, JSON.stringify(state))
    }
  }
})
Use attribute visibility in combination with responsive design to hide less important columns on mobile devices by default.
The attrs prop on <VueList> can be an array of strings or objects with name and label properties.

Next steps

VueList props

Learn about the attrs prop

State persistence

Save attribute preferences