Skip to content

Hello CRM!

While our hello-world component might be great, it does not do much to interact with the webclient.
This tutorial is a continuation of the first tutorial, and aims to create a more advanced component than hello-world.

We'll write a component that, when clicked, sends a request to the API to update the name of the current limeobject and notifies the User that the action was completed.

Generating a new component

In the hello-world tutorial, we named our package Cool Package and we'll continue working within that same package.

If you named your package something other than what was suggested, the folder name and component name will reflect whatever name you chose for your package.

Within the main folder of your package limepkg-cool-package, if that is the name of the folder as discussed above,
create a new component with the lime-project command:

lime-project generate web-component hello-crm

Just as with our first component, we can remove most of the code and add more as needed.

The path to the component should be src\components\lwc-limepkg-cool-package-hello-crm\lwc-limepkg-cool-package-hello-crm.tsx

Modify the generated component by removing the unnecessary code.
The modified component should look like this:

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

@Component({
    tag: "lwc-limepkg-cool-package-hello-crm",
    shadow: true,
})
export class HelloCrm implements LimeWebComponent {
    /**
     * @inherit
     */
    @Prop()
    public platform: LimeWebComponentPlatform;

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

    @Element()
    public element: HTMLElement;

    public render() {
        return "Hello, CRM!";
    }
}

Configure it in the webclient

To make the component appear in the webclient it needs to be added to a configuration. In Lime Admin, go to the Views configuration and then select the Company type. In the Card section, there should be another section called Web Components. Add the component in there and enter the name of the component, i.e. lwc-limepkg-cool-package-hello-crm.

Connecting to the state

To get the name of the company we need to define a variable in our component and connect it to the state:

Add 'LimeObject' and 'SelectCurrentLimeObject' to the imports from '@limetech/lime-web-components'  
Add 'State' to the imports from '@stencil/core'  
import {
    LimeWebComponent,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
    LimeObject,
    SelectCurrentLimeObject,
} from '@limetech/lime-web-components';
import { Component, h, Prop, State } from '@stencil/core';
Add a variable named 'company' to the component and decorate it with the '@State()' and '@SelectCurrentLimeObject()' decorators
export class HelloCrm implements LimeWebComponent {
    /**
     * @inherit
     */
    @Prop()
    public platform: LimeWebComponentPlatform;

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

    @Element()
    public element: HTMLElement;

    @State()
    @SelectCurrentLimeObject()
    private company: LimeObject;

    ...
}

The SelectCurrentLimeObject decorator will set the value of the company state variable to contain the current company from the context. To render the name, we simply have to modify our render method like so:

public render() {
    ...
    return <h2>Hello, {this.company.name}!</h2>;
}

Conditional rendering

To make it a bit more interesting, we can add some conditional rendering and only render the component if a certain criteria is met.

To do this, lets modify our render method to check if the company is active.

The property to check if a company is active or not is buyingstatus:

public render() {
    if (this.company.buyingstatus !== 'active') {
        return;
    }

    return <h2>Hello, {this.company.name}!</h2>;
}

Now, if we visit a company card where the company is inactive, we will not see our component at all, it will only render for active companies.

Let's make the component do something a bit more interesting. Let's add a button that changes the company name once it's been pressed.

Using the Core API

Before we add the button, we need to import some services and write the function that our button will call.
We are going to use the http service from the platform to call the Core API and update the company name.

Add 'PlatformServiceName' and 'HttpClient' to the imports from '@limetech/lime-web-components'  
import {
    LimeWebComponent,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
    LimeObject,
    SelectCurrentLimeObject,
    PlatformServiceName,
    HttpClient,
} from '@limetech/lime-web-components';

We want to access the http service from within our component, so let's write a getter that will make this service
available within our component:

private get http(): HttpClient {
    return this.platform.get(PlatformServiceName.Http);
}

Now that we've got our HttpClient within the component, let's write a function that sends a http request to the API
and updates the name of the company.

We await this.http and use a put() method. To the endpoint URL we append this.context.id which references our
component context prop.
We pass in an object containing the key of the property we want to update, and the new value. We're adding the string
Super to this.company.name which references our components private company state variable which, you may recall,
is being set by the SelectCurrentLimeObject state decorator:

private handleClick = async () => {
    await this.http.put(`api/v1/limeobject/company/${this.context.id}/`, {
        name: `Super ${this.company.name}!`
    });
};

Let's add the button to the render method that changes the name of the company once it has been pressed.
We're now wrapping the elements returned within an array:

public render() {
    if (this.company.buyingstatus !== 'active') {
        return;
    }

    return [
        <h2>Hello, {this.company.name}!</h2>,
        <limel-button
            primary
            label="Click me!"
            onClick={this.handleClick}
        />,
    ];
}

After these changes, the limel-button within our component will call handleClick
when clicked, and the company name should update.

Before we test it out, let's add a notification feature.

Notify the User with the use of the snackbar and Notification service

We need to get the Notification service, so let's write another small getter within our component, but first
we need to add to our imports:

Add 'Notifications' to the imports from '@limetech/lime-web-components'  
import {
    LimeWebComponent,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
    LimeObject,
    SelectCurrentLimeObject,
    PlatformServiceName,
    HttpClient,
    Notifications,
} from '@limetech/lime-web-components';

And write our getter:

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

With the getter in the component getting the notification service, we can easily invoke it using
this.notification.notify('Message here'), so let's do that within our handleClick function
and pass in a relevant message to the user. We'll store the current company name in a variable called previousName and use that within our notification:

private handleClick = async () => {
    const previousName = this.company.name;
    await this.http.put(`api/v1/limeobject/company/${this.context.id}/`, {
        name: `Super ${this.company.name}!`,
    });
    this.notification.notify(
        `Company name has been updated! from: ${previousName} to: ${this.company.name}`
    );
};

Our final component should look something like this:

import {
    LimeWebComponent,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
    LimeObject,
    SelectCurrentLimeObject,
    PlatformServiceName,
    HttpClient,
    Notifications,
} from '@limetech/lime-web-components';
import { Component, h, Prop, State } from '@stencil/core';

@Component({
  tag: "lwc-limepkg-cool-package-hello-crm",
  shadow: true,
})
export class HelloCrm implements LimeWebComponent {
    /**
     * @inherit
     */
    @Prop()
    public platform: LimeWebComponentPlatform;

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

    @SelectCurrentLimeObject()
    @State()
    private company: LimeObject;

    public render() {
        if (this.company.buyingstatus !== 'active') {
            return;
        }

        return [
            <h2>Hello, {this.company.name}!</h2>,
            <limel-button
                primary
                label="Click me!"
                onClick={this.handleClick}
            />,
        ];
    }

    private handleClick = async () => {
        const previousName = this.company.name;
        await this.http.put(`api/v1/limeobject/company/${this.context.id}/`, {
            name: `Super ${this.company.name}!`,
        });
        this.notification.notify(
            `Company name has been updated! from: ${previousName} to: ${this.company.name}`
        );
    };

    private get http(): HttpClient {
        return this.platform.get(PlatformServiceName.Http)
    }

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

Displaying our new component on a card

Once again we have to open up Lime Admin to add our component to the Company card.
To make the component appear in the webclient, it needs to be added to a configuration.
In Lime Admin, go to the Views configuration and then select the Company type.

Within the Card section, in the section called Web Components, we can replace our previous component lwc-limepkg-cool-package-hello-world by replacing that name with the name of our new component, i.e. lwc-limepkg-cool-package-hello-crm.

Try it out!

Let's try it out by pressing the button and see that the name of the company is updated automatically!
The user is notified of the change via the snackbar (popup toast message at the bottom of the page)!