Invoke command from React.Component?

Hi,

I’m building a widget extension with a backend service. The general idea is to provide the user with a form which will create files based on the user input on submit.

The widget (which extends ReactWidget) instantiates a React.Component on render():

    protected render(): React.ReactNode {
        return <TheiaSwizardExtensionView />;
    }

That component provides the form and handles user input manipulation by storing values into its state. Once the user clicks “Submit”, I would like to be able to trigger a callback in the widget (the “parent” ReactWidget), which holds the CommandRegistry, with the ReactNode state as argument to that callback.

I failed to find examples in Theia but I might have overlooked something.

Could someone provide me with any pointer?

Thank you!

I am not sure if I got this, but you can pass down the service in the props just like in pure React. Here is an example, if you are looking for something like this.

1 Like

Thank you, I’m currently looking into it. I must say I am not familiar with React and I’m struggling to initialize my view’s props. Here is the complete snippet for the form component:

import * as React from 'react';

import { AlertMessage } from '@theia/core/lib/browser/widgets/alert-message';

import { Sensor } from './theia-swizard-extension-widget';

export class SensorView extends React.Component<Sensor> {
    render(): JSX.Element {
        return <React.Fragment>
            <ul>
                <li>Brand: {this.props.brand}</li>
                <li>Model: {this.props.model}</li>
                <li>Name: {this.props.name}</li>
            </ul>
        </React.Fragment>;
    }
}

export class TheiaSwizardExtensionView extends React.Component<{}, Sensor> {

    constructor(props: {}) {
        super(props);

        this.state = {
            brand: '',
            model: '',
            name: ''
        }
    }

    render(): JSX.Element {
        const header = `From this panel, you can create a new sensor driver using a base skeleton.`;
        return <div id="widget-container">
            <AlertMessage type='INFO' header={header} />

            <h2>New Sensor</h2>

            <SensorView brand={this.state.brand} model={this.state.model} name={this.state.name} />

            <form onSubmit={this.handleSubmit}>
                <label>Brand: <input value={this.state.brand} onChange={this.updateBrand} /></label>
                <label>Model: <input value={this.state.model} onChange={this.updateModel} /></label>
                <input type="submit" value="OK" />
            </form>
        </div>;
    }

    protected handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        this.getName();
    }

    protected updateBrand = (e: React.ChangeEvent<HTMLInputElement>) => this.setState({
        brand: e.currentTarget.value
    });

    protected updateModel = (e: React.ChangeEvent<HTMLInputElement>) => this.setState({
        model: e.currentTarget.value
    });

    protected getName = () => this.setState({
        name: `${this.cleanString(this.state.brand)}_${this.cleanString(this.state.model)}`
    });

    protected cleanString = (s: string) => s.toUpperCase().replace(/ /g, "_");
}

And here is is how it is rendered, from the widget:

    protected render(): React.ReactNode {
        return <TheiaSwizardExtensionView />;
    }

Noob alert: I didn’t find a way to pass down any value to TheiaSwizardExtensionView from the widget :frowning:

No worries. I added a quick example. Open the Sample Unclosable View and see how it works. Also, check the console (in the dev tools). My example does not call the command service eventually, but it’s there. You can use it. I hope this helps.

1 Like

This is great. Thank you very much. I got close but you just nailed it!

Now I just have to find out how to declare commands which accept arguments :slight_smile:

You can take a look at our test cases for an example on a command that can accept arguments:

You can take a look how the command is registered, and how to invoke it :slight_smile:

1 Like

You know what? That’s exactly what I did, and it worked out just the way it should have :smiley:

Thank you again for your promptness. It’s a pleasure to work with Theia with such great help.

1 Like