Simple Example to implement VS Code TreeDataProvider with JSON data

Viewed 6008

I'm trying to add a Tree View to my VS Code extension. Data is a complex JSON object. I stuggle to get this to working as the examples aren't straight forward to me.

Lets say I have a simple object:

"cars": [
  { "name":"Ford", "models":[ "Fiesta", "Focus", "Mustang" ] },
  { "name":"BMW", "models":[ "320", "X3", "X5" ] }
]

I would like to render this in the treeview as follows:

Cars
 > Ford
   > Fiesta
   > Focus
   > Mustang
 > BMW
   > 320
   > X3
   > X5

Any pointers how to achieve this, or know of an repo I can look at that does something similar?

2 Answers

Here's a straightforward implementation:

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  vscode.window.registerTreeDataProvider('exampleView', new TreeDataProvider());
}

class TreeDataProvider implements vscode.TreeDataProvider<TreeItem> {
  onDidChangeTreeData?: vscode.Event<TreeItem|null|undefined>|undefined;

  data: TreeItem[];

  constructor() {
    this.data = [new TreeItem('cars', [
      new TreeItem(
          'Ford', [new TreeItem('Fiesta'), new TreeItem('Focus'), new TreeItem('Mustang')]),
      new TreeItem(
          'BMW', [new TreeItem('320'), new TreeItem('X3'), new TreeItem('X5')])
    ])];
  }

  getTreeItem(element: TreeItem): vscode.TreeItem|Thenable<vscode.TreeItem> {
    return element;
  }

  getChildren(element?: TreeItem|undefined): vscode.ProviderResult<TreeItem[]> {
    if (element === undefined) {
      return this.data;
    }
    return element.children;
  }
}

class TreeItem extends vscode.TreeItem {
  children: TreeItem[]|undefined;

  constructor(label: string, children?: TreeItem[]) {
    super(
        label,
        children === undefined ? vscode.TreeItemCollapsibleState.None :
                                 vscode.TreeItemCollapsibleState.Expanded);
    this.children = children;
  }
}

And in package.json:

{
    [...]
    "contributes": {
        "views": {
            "explorer": [
                {
                    "id": "exampleView",
                    "name": "exampleView"
                }
            ]
        }
    }
}

You might want to have a way of creating the data dynamically from your JSON data, but to keep the example as simple as possible I just create it statically in the constructor.

I kept the return object for getChildren as any[] as I have different data types being return w.r.t different parent. However clicking on the Child is again calling the getChildren from same DataProvider instead of calling the getChildren from DataProvider of child. Any suggestion is greatly appreciated.

  • type1
    • type2
    • type2
  • type1
    • type3
    • type3

In DataProvider of type1, The getChildren get called and return type2 depending on a condition, returns type3 in another case. However clicking on type2 is again calling getChildren from the same DataProvider instead of calling from type2 provider.

Related