batjko
batjko

Reputation: 1062

How to listen to events in vscode's TreeDataProvider?

I'm playing with building a vscode extension, using the TreeDataProvider API. I have a list of things showing, each TreeItem a composed label string, all works fine.

What I am missing is a way of reacting to click events on any of the items. VSCode selects the item when you click on it, but I'd like to listen to that event, get the item in question etc... It's not obvious to me from the docs.

In general, customizing the TreeItem is severely lacking, e.g. being able to colorize the label or pass a more flexible UI component in instead of just a string... Maybe I'm missing something?

Upvotes: 6

Views: 3882

Answers (2)

Mark
Mark

Reputation: 180805

Apparently added after the question and answer, there are these "TreeViewEvents":

onDidChangeSelection: Event<TreeViewSelectionChangeEvent<T>>

onDidChangeVisibility: Event<TreeViewVisibilityChangeEvent>

onDidCollapseElement: Event<TreeViewExpansionEvent<T>>

onDidExpandElement: Event<TreeViewExpansionEvent<T>>

from TreeView api

Using this sample code from one of my extensions:

const viewSelection = this.tabView.onDidChangeSelection(
  debounce( async event => {
    ...
  }, 1000, {isImmediate: true}) 
);

event.selection will be an array of your extended TreeItems that were selected.

Upvotes: 2

Gama11
Gama11

Reputation: 34138

VSCode selects the item when you click on it, but I'd like to listen to that event, get the item in question etc...

You can use TreeItem.command to run some command when a tree item is selected, and then register a callback for that command. Here's a simple example that traces the label of a tree item to the console:

'use strict';
import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext) {
    vscode.window.registerTreeDataProvider("exampleTreeView", new ExampleTreeProvider());
    vscode.commands.registerCommand("exampleTreeView.selectNode", (item:vscode.TreeItem) => {
        console.log(item.label);
    });
}

export class ExampleTreeProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
    getTreeItem(element: vscode.TreeItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
        return element;
    }

    getChildren(element?: vscode.TreeItem): vscode.ProviderResult<vscode.TreeItem[]> {
        if (element == null) {
            var item = new vscode.TreeItem("Foo");
            item.command = {
                command: "exampleTreeView.selectNode",
                title: "Select Node",
                arguments: [item]
            };
            return [item];
        }
        return null;
    }
}
"contributes": {
    "views": {
        "explorer": [
            {
                "id": "exampleTreeView",
                "name": "Example Tree View"
            }
        ]
    }
},

The command can be any arbitrary string, but I like to "scope" it by prefixing the view ID. It's important to pass the item itself via arguments if you want to access any of its properties in the callback.

In general, customizing the TreeItem is severely lacking, e.g. being able to colorize the label or pass a more flexible UI component in instead of just a string...

That sounds like an accurate assessment, the API is a bit limiting in some ways. If you need more freedom, the recently introduced Webview API might be a good alternative. Note that that would mean implementing your own tree view from scratch using HTML/CSS/JS.

Upvotes: 12

Related Questions