Skip to content

Conditions

Conditions are reusable objects registrable to the condition registry, which act as wrappers for evaluation functions callable from within any web component in the CRM. Every condition is specified by

  1. A string-based type, describing what object we are evaluating (e.g., "limeobject"), useful for type hinting
  2. An evaluation function, a function as explained below
  3. A string-based id, a unique identifier for this condition

In turn, evaluation functions are callback functions returning a boolean value. That is, they return either true or false. This may seem trivial, but evaluation functions are the perfect tool for when we want to achieve reusable "if this holds, then perform this action"-kind-of behaviour.

Every evaluation function requires as input

  1. A subject, which encodes an object—such as a limeobject or a string—related to the type of the condition
  2. Parameters, describing additional data besides the subject that the evaluation function expects to construct an output

Examples

Because of their generality, conditions can be quite difficult to grasp when presented in this abstract form. It helps to look at a concrete examples to better understand conditions.

There exist hard-coded conditions needed for the CRM to work that are registered in the loader on every page refresh.

Limeobject-matches-filter

In a typical solution, you can expect a number of conditions to be evaluated on the contextual action bar when you open a card to determine the visibility of items. The boolean output of the corresponding evaluation functions simply specifies whether an action should be visible or not.

A condition performing this function is the condition with ID limeobject-matches-filter, whose evaluation function returns true if and only if a limeobject matches a given filter expression. The details can be explored in the article on configuring custom visibility.

The code for this condition is as follows:

limeobject-matches-filter.ts
const limeObjectMatchesFilter: Condition<Action> = {
    id: "limeobject-matches-filter",
    type: "action",
    evaluate: (subject: Action, params: Expression): boolean => {
        const limeobject = (subject.command as any).limeobject;
        const filter = params as Expression;

        return matchFilter(filter, limeobject); // (1)!
    },
};
    • This is a call to a function internal to the crm-components repository

Is-past-8

A more contrived example illustrating parameterless evaluation functions is one that checks if it is past 8 o'clock according to the system's local time zone.

is-past-8.ts
const isPastEight: Condition = {
    id: 'is-past-8',
    type: 'action',
    evaluate: (): boolean => {
        return date.getHours() >= 8; // (1)!
    },
};
    • Note that if equal to 8, then the additional seconds still imply it is past 8

Note

At present (October 2023), evaluation functions do not support asynchronous function calls. This implies that we offer no means of communicating with an external API, internal endpoint or database from within an evaluation function.

Registering Your Own Condition in a Plugin

If you were to register a condition yourself—let's call it myCondition—you would want to add it to your package in the loader using code similar to the below snippet

loader.ts
import {
    ConditionRegistry,
    LimePluginLoader,
    LimeWebComponentContext,
    LimeWebComponentPlatform,
    PlatformServiceName,
} from '@limetech/lime-web-components';
import { Component, Prop } from '@stencil/core';
import { myCondition } from '../my-condition';

@Component({
    tag: 'lwc-limepkg-my-plugin-loader',
    shadow: true,
})
export class Loader implements LimePluginLoader {
    /**
     * @inheritdoc
     */
    @Prop()
    public platform: LimeWebComponentPlatform;

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

    ...

    public componentWillLoad() {
        ...
        this.registerConditions();
        ...
    }

    ...

    private registerConditions() {
        this.conditions.addCondition(myCondition);
    }

    ...

    private get conditions(): ConditionRegistry {
        return this.platform.get(PlatformServiceName.ConditionRegistry);
    }
}

Type Guarding

At present, we have two preexisting types defined according to

types.ts
type LimeObjectCondition = Condition<LimeObject> & {
    type: "limeobject";
};

type ActionCondition = Condition<Action> & {
    type: "action";
};

As well as associated helper functions

types.ts
function isLimeObjectCondition(
    condition: Condition
): condition is Condition<LimeObject> {
    return condition.type === "limeobject";
}

function isActionCondition(
    condition: Condition
): condition is Condition<Action> {
    return condition.type === "action";
}

These helpers give you the benefit of static type checking. They can be imported from @limetech/lime-web-components. You can follow the same approach to implement type guarding for your own custom types.