Skip to content

Expand & Collapse

Objects and arrays are collapsible. State is tracked per node and persists, so exploring deep structures never loses your place.

Initial State

The expanded prop sets the starting state for every node:

vue
<!-- Start expanded (default) -->
<JsonViewer :data="data" :expanded="true" />

<!-- Start collapsed -->
<JsonViewer :data="data" :expanded="false" />

Interactive Controls

Expand All / Collapse All

For a root object or array, the component shows Expand All and Collapse All buttons automatically:

vue
<JsonViewer :data="data" />

Click to Toggle

Users can toggle a node by clicking any of:

  1. the key (e.g. "hobbies"),
  2. the type indicator / brackets ({, […]),
  3. the count label (3 keys, 5 items),
  4. the type badge (obj, count).
obj{
"users":2[
obj{
"id": 1,
"name": "Alice",
"role": "admin"
},
obj{
"id": 2,
"name": "Bob",
"role": "user"
}
],
"settings":obj{
"theme": "dark",
"notifications":obj{
"email": true,
"push": false
}
}
}

State Persists Across Collapse

This is the important part. Expand a nested node, collapse one of its ancestors, then expand that ancestor again — the nested node is exactly where you left it. Node state is keyed by a stable path and stored above the part of the tree that unmounts, so collapsing a parent never destroys the state inside it.

Why this matters

In many tree viewers, collapsing a parent throws away all the expand/collapse state inside it, forcing you to re-drill every time. Here it just works.

Programmatic Control

Bind expanded to a ref. It's reactive — changing it re-seeds the whole tree.

vue
<script setup lang="ts">
  import { ref } from 'vue';
  import { JsonViewer } from '@anilkumarthakur/vue3-json-viewer';
  import '@anilkumarthakur/vue3-json-viewer/styles.css';

  const expanded = ref(true);
  const data = {
    /* … */
  };
</script>

<template>
  <button @click="expanded = !expanded">
    {{ expanded ? 'Collapse All' : 'Expand All' }}
  </button>

  <JsonViewer
    :data="data"
    :expanded="expanded"
  />
</template>

No :key hack needed

Earlier versions of these docs recommended :key="String(expanded)" to force a remount. That was a workaround for a state-loss bug that is now fixed. Remove it — binding :expanded is enough, and the :key hack would throw away the persistence described above.

Reacting to Toggles

To observe or persist toggles, listen to the toggle event:

vue
<JsonViewer :data="data" @toggle="(e) => console.log(e.path, e.expanded)" />

See Events & Persistence for saving state across reloads.

Visual Indicators

Collapsed:

  • Object → {...} + count badge (3 keys)
  • Array → [...] + count badge (5 items)

Expanded:

  • Object → {, children, }
  • Array → [, items, ]

Type Badges

TypeBadgeCollapsed example
Objectobj"user": obj {...} 3 keys
Arraycount"items": 5 [...] 5 items
Empty arrayempty"list": empty []

Tips

Large data

For very large JSON, start with :expanded="false" — collapsed subtrees aren't rendered, so the initial paint is much faster. See Large JSON.

Released under the MIT License.