Anyone been succesful with integrating VueJs-based custom widget?

Tried

protected readonly SomeComponentConstructor = Vue.extend({
// `createElement` is inferred, but `render` needs return type
render(createElement: any): VNode {
return createElement(<div> <p> Hello </p> </div>)
}
})


@postConstruct()
protected init(): void {
    this.id = ServerExplorerWidget.ID;
    this.title.caption = ServerExplorerWidget.LABEL;
    this.title.label = ServerExplorerWidget.LABEL;
    this.title.closable = true;
    this.title.iconClass = 'server-tab-icon';


    let Component = new this.SomeComponentConstructor({

    })

    Component.$mount(this.node)

}

but results in:

logger-protocol.ts:112 root ERROR TypeError: Cannot add property _Ctor, object is not extensible
at Function.Vue.extend (http://localhost:8080/43.bundle.js:22345:67)

Google not giving me much to go on and debugging deep into Vue. Wonder if the DOM isn’t in the right state at this point.

[original thread by Max Hillaert]

[Max Hillaert]

I got this working, in case anyone is interested.

@injectable()
export class ServerExplorerWidget extends BaseWidget {

    static ID = 'serverexplorer';
    static LABEL = 'Server Explorer';

    static createContainer(parent: interfaces.Container): Container {
        const child = new Container({ defaultScope: 'Singleton' });
        child.parent = parent;
        child.bind(ServerExplorerWidget).toSelf();
        return child;
    }
    static createWidget(parent: interfaces.Container): ServerExplorerWidget {
        return ServerExplorerWidget.createContainer(parent).get(ServerExplorerWidget);
    }
    /// Where the library is basically built using vue-cli library target build on a myLib.vue file
    private Component = require("vue-js-component-library/dist/myLib.common.js")
    private SomeComponentConstructor = Vue.extend(this.Component)
    private componentInstance = new this.SomeComponentConstructor({})


    protected onUpdateRequest(msg: Message): void {
        super.onUpdateRequest(msg);
        //need to create intermediate element , otherwise vuejs will vandalise the element, making theia UI framework to lose track
        // resulting in odd behaviour, like your vue component staying visible after switching tabs
        let element = document.createElement("div")
        this.node.appendChild(element)
        this.componentInstance.$mount(element)
    }

    @postConstruct()
    protected init(): void {
        this.id = ServerExplorerWidget.ID;
        this.title.caption = ServerExplorerWidget.LABEL;
        this.title.label = ServerExplorerWidget.LABEL;
        this.title.closable = true;
        this.title.iconClass = 'server-tab-icon';
        this.update();
    }
}

So what’s the trick?

[Max Hillaert]

Well I was hung up on making the TSX example working in the original code above, even though I had no intention of using TSX. I want no specific UI code in my theia extension, for maximum reuse. I have some UI component Library I use in our VSCode plugin, dashboards etc which are already prepackaged disted vuejs components, which I want to reuse.

There is an issue with VueJS and TSX I think. There are various articles/forum posts about difficulties around it. You need to probably experiment with turning off “React” in ts compiler options and let babel take care of the JSX stuff, but I didn’t pursue it. It might clash with theia compilation setup, who knows.

Not using TSX , but creating DOM elements manually is also an alternative, but mental.

[Max Hillaert]

I’m now going to try and pass in viewmodel and adapt vuejs component events to the theia extension I’m working on. I’ll complete the example for anyone who cares.

Just out of curiosity: why do you want to go with VueJS instead of React?

[Max Hillaert]

Because we already created components in vuejs. I’ve got a server explorer component for example made in vuejs. It runs as a web view in vscode. I don’t want to have to recreate it.

[Max Hillaert]

Just for reuse reasons and previously committed to UI stacks. Neither of us are proper UI devs, and don’t want to have to learn multiple UI stacks across our language tooling. That sort of thing.

[Max Hillaert]

Updated the working example above. You need to create an intermediate HtmlElement over this.node, as vuejs will vandalise it when you mount vuejs on an element, clashing with theia UI framework, resulting on component staying visible when switching to other side tabs

You could run vscode webview in Theia just fyi