elsa-workflows / elsa-workflows/elsa-studio
Enhancement Proposal: Conditional Inputs in Elsa 3
- Dominant language
- C#
- Stars
- 301
- Forks
- 181
- Avg merge
- 17h 12m
- Merged PRs (30d)
- 42
Description
**Background:** At Nuvotex GmbH, we frequently relied on a valuable feature in Elsa 2 that allowed us to dynamically show or hide inputs based on the current state of the input form. This feature enabled us to create more efficient and user-friendly activities and workflows. Unfortunately, this functionality is missing in Elsa 3, which limits our ability to customize our input forms.
**Use Case:** Consider an activity that interacts with a specific service. With conditional inputs, we can tailor the behavior of this activity based on the user’s input. For instance, imagine an “API call activity” where we need to choose between different endpoints. By using a conditional dropdown, we can dynamically display relevant input fields for the selected API call. This approach streamlines the process and eliminates the need to create multiple activities for a single service.
**Benefits:**
1. **Flexibility:** Users can adapt their workflows by adjusting input visibility based on context.
2. **Simplicity:** Avoid cluttering the interface with unnecessary fields, improving usability.
3. **Efficiency:** Reduce redundancy by handling variations within a single activity.
Introducing conditional inputs in Elsa 3 would empower users to build more dynamic and efficient workflows. By reinstating this feature, we enhance the platform’s versatility and user-friendliness.
**Implementation:**
To achieve the functionality described above, we seamlessly integrated this feature directly into Elsa.Studio, without any modifications to Elsa.Core. The essential payloads, which encapsulate the desired behavior, are serialized and stored in the ‘Description’ attribute of the Input decorator. Elsa.Studio then deserializes this description and updates the components based on the payload received.
We’ve introduced two new input decorators in our workflow server: **StateDropdownInput** and **ConditionalInput**. Let’s delve into the specifics:
1. StateDropdownInput:
- This decorator defines all permissible states.
- Its first parameter is an array of strings with the following format:
- [token, value, state-id - optional, description - optional]
- We have three token types, each implicitly specifying the number of following parameters:
- _ConditionalInputOptions.WithoutDescription_:
token, value
- _ConditionalInputOptions.WithDescription_:
token, value, description,
- _ConditionalInputOptions.WithIdAndDescription_:
token, value, state-id, description
- Our choice of an array approach stems from the need to serialize these custom inputs and store them in the Description attribute. Unfortunately, due to a C# limitation, we couldn’t create additional custom attributes. The Description attribute can only be overridden in the constructor. If we use a setter function within the Decorator, the value set isn’t available in the constructor. Implementing this directly in Elsa.Core would simplify matters, allowing us to utilize attributes.
2. Multiple StateDropdownInputs:
- Each input contributes its own state to the InputsTab.
- These states can then be leveraged by the ConditionalInput.
In all other respects, the StateDropdownInput behaves like a standard dropdown input, sharing attributes with those defined in Elsa.Core.
Consider the following concrete example:

In this scenario, let’s focus on the first entry within the list. Specifically, we encounter the _ConditionalInputOptions.WithDescription_ token. With this token, we can elegantly declare that we have a dropdown entry associated with the _ZammadApiNames.GetTicket_ value. The description for this input is succinctly defined as “Fetches a ticket by ID.”
When a user selects this value within the Elsa.Core environment, the state of the _InputsTab_ dynamically updates and triggers a rerender.
**ConditionalInput**
When working with the state declared in _StateDropdownInput_, we can leverage the _ConditionalInput_ decorator. This decorator functions similarly to the standard Input decorator, with a slight difference: the first parameter in its constructor is a list of accepted states, and the second parameter specifies the input description. Much like the _StateDropdownInput_, it also serializes custom payload information within the _Description_ attribute.

Here’s how it works:
1. **Accepted States:** We check whether the current state of the InputsTab matches any of the specified states. If it does, the input associated with the decorator is displayed; otherwise, it remains hidden.
2. **Multiple States:** To show the input when the state is either ZammadApiNames.AddArticle or ZammadApiNames.GetTicket, simply provide an array of accepted states: [ZammadApiNames.AddArticle, ZammadApiNames.GetTicket].
3. **AND Functionality:** Currently, the input appears if the InputsTab state contains at least one value declared in the array. The “AND” functionality (requiring multiple specific states simultaneously) is not yet implemented, as it hasn’t been necessary for our use case.
If you’re interested in exploring our current implementation of this feature, we’d be more than happy to collaborate. Feel free to reach out, and we can create a pull request with the code changes we’ve made.
Contributor guide
Assessment
This issue has not been assessed yet.