Skip to content

Hello Command!

This guide will show how to generate a new command, connect it to a handler, and trigger the command from a menu in the table view inside the webclient.

Generate a command

The module needs a translation module to exist. In case you don't have that yet in your package or solution, run this command inside your project

lime-project generate translation-module

Afterwards you can generate a new command

lime-project generate command hello

This will generate a command class and its corresponding handler.

The command class src/commands/hello/hello.command.ts should look like this:

import { Command } from "@limetech/lime-web-components";

@Command({
  id: "my-package.hello",
})
export class HelloCommand {}

The handler src/commands/hello/hello.handler.ts should look like this:

import { CommandHandler } from '@limetech/lime-web-components';
import { HelloCommand } from './hello.command';

export class HelloHandler implements CommandHandler {
    public handle(command: HelloCommand) {}
}

Implement the handler

Our command is only going to show a notification when the command is handled, but a more common use case when it is triggered from a menu is probably to open a dialog.

Let's modify our command handler to be able to show a notification by adding Notifications to the imports from @limetech/lime-web-components.

import {
    CommandHandler,
    Notifications
} from '@limetech/lime-web-components';

We then need to ensure our CommandHandler can accept the notification service.
Let's add a constructor to our class.

constructor(private notifications: Notifications) {}

We'll pass in the notification service from our loader component which we'll modify next.

Our handler should now look like this:

import { CommandHandler, Notifications } from '@limetech/lime-web-components';
import { HelloCommand } from './hello.command';

export class HelloHandler implements CommandHandler {
    constructor(private notifications: Notifications) {}

    public handle(command: HelloCommand) {
        this.notifications.notify('Running HelloCommand!');
        console.log(command);
    }
}

Register the command

In order to run this command, we need to register it to the handler when the application starts. A good place to do this is in the Loader component loaded at the start of a session. In the componentWillLoad lifecycle hook, we can add the code to register our command and make it useable from within the application.

Open the loader which should be located here src/components/lwc-my-plugin-loader/lwc-my-plugin-loader.tsx

The default loader for the package should look like this:

import {
    LimePluginLoader,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
} from '@limetech/lime-web-components';
import { Component, Prop } from '@stencil/core';

// NOTE: Do NOT remove this component, it is required to run the plugin correctly.
// However, if your plugin has any code that should run only once when the application
// starts, you are free to use the component lifecycle methods below to do so.
// The component should never render anything, so do NOT implement a render method.

@Component({
    // ⚠️ WARNING! Do not change the tag name of this component unless you also
    // change the name of the package. The tag name should be
    // lwc-<package-name>-loader, e.g. lwc-limepkg-cool-package-loader
    tag: 'lwc-limepkg-cool-package-loader',
    shadow: true,
})
export class Loader implements LimePluginLoader {
    /**
     * @inherit
     */
    @Prop()
    public platform: LimeWebComponentPlatform;

    /**
     * @inherit
     */
    @Prop()
    public context: LimeWebComponentContext;

    public connectedCallback() {}

    public componentWillLoad() {}

    public componentWillUpdate() {}

    public disconnectedCallback() {}
}

Add CommandBus, PlatformServiceName and Notifications to the imports from @limetech/lime-web-components

import {
    CommandBus,
    Notifications,
    PlatformServiceName,
    LimePluginLoader,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
} from '@limetech/lime-web-components';
import { Component, Prop } from '@stencil/core';

We also need to import our Command class and Handler

import { HelloCommand } from 'src/commands/hello/hello.command';
import { HelloHandler } from 'src/commands/hello/hello.handler';

Let's get both the Notification service and commandBus

    private get notificationService(): Notifications {
        return this.platform.get(PlatformServiceName.Notification);
    }

    private get commandBus(): CommandBus {
        return this.platform.get(PlatformServiceName.CommandBus);
    }

And now let's implement the functionality in the loader by modifying the componentWillLoad() function

...
export class Loader implements LimePluginLoader {
    ...
    private commandBus: CommandBus;

    public componentWillLoad() {
        const helloHandler = new HelloHandler(this.notificationService);
        this.commandBus.register(HelloCommand, helloHandler);
    }
}

Our Loader component should look like this:

import {
    LimePluginLoader,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
    CommandBus,
    Notifications,
    PlatformServiceName,
} from '@limetech/lime-web-components';
import { HelloCommand } from 'src/commands/hello/hello.command';
import { HelloHandler } from 'src/commands/hello/hello.handler';
import { Component, Prop } from '@stencil/core';

// NOTE: Do NOT remove this component, it is required to run the plugin correctly.
// However, if your plugin has any code that should run only once when the application
// starts, you are free to use the component lifecycle methods below to do so.
// The component should never render anything, so do NOT implement a render method.

@Component({
    // ⚠️ WARNING! Do not change the tag name of this component unless you also
    // change the name of the package. The tag name should be
    // lwc-<package-name>-loader, e.g. lwc-limepkg-cool-package-loader
    tag: 'lwc-limepkg-cool-package-loader',
    shadow: true,
})
export class Loader implements LimePluginLoader {
    /**
     * @inherit
     */
    @Prop()
    public platform: LimeWebComponentPlatform;

    /**
     * @inherit
     */
    @Prop()
    public context: LimeWebComponentContext;

    public connectedCallback() {}

    public componentWillLoad() {
        const helloHandler = new HelloHandler(this.notificationService);
        this.commandBus.register(HelloCommand, helloHandler);
    }

    public componentWillUpdate() {}

    public disconnectedCallback() {}

    private get notificationService(): Notifications {
        return this.platform.get(PlatformServiceName.Notification);
    }

    private get commandBus(): CommandBus {
        return this.platform.get(PlatformServiceName.CommandBus);
    }
}

Trigger the command

To trigger the command manually, you can simply send it to the commandbus from another component—say a newly generated one containing a limel-button. We could use the Hello World component that we created in the first tutorial:

Don't forget to import the command

import { HelloCommand } from 'src/commands/hello/hello.command';
...

import {
    CommandBus,
    LimeWebComponent,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
    PlatformServiceName,
} from '@limetech/lime-web-components';
import { Component, h, Prop } from '@stencil/core';
import { HelloCommand } from 'src/commands/hello/hello.command';

@Component({
    tag: 'lwc-limepkg-cool-package-hello-world',
    shadow: true,
    styleUrl: 'lwc-limepkg-cool-package-hello-world.scss',
})
export class HelloWorld implements LimeWebComponent {
    /**
     * @inherit
     */
    @Prop()
    public platform: LimeWebComponentPlatform;

    /**
     * @inherit
     */
    @Prop()
    public context: LimeWebComponentContext;

    public render() {
        return (
            <limel-button
                label={'Hello World!'}
                outlined={true}
                icon={'house_stark'}
                onClick={this.handleClick}
            />
        );
    }

    private handleClick = () => {
        const command = new HelloCommand();
        this.commandBus.handle(command);
    };

    private get commandBus(): CommandBus {
        return this.platform.get(PlatformServiceName.CommandBus);
    }
}

...

In order to add it to a menu in the table view inside the webclient, we need to configure the menu on the Administrators page to register our command.
This we do by adding an action under the table view for the desired limetype with an id of my-package.hello.

Note

This used to be done, and could be done, by adding the following actions JSON snippet to the Table section for the desired limetypes in the View Editor.

{
    "actions": [
        {
            "id": "my-package.hello"
        }
    ]
}

This can also be done inside the plugin's configuration, by providing the corresponding menu in a web-component.