Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expressions: Extend with more functionality #646

Closed
11 tasks done
Tracked by #115
olemartinorg opened this issue Aug 12, 2022 · 3 comments
Closed
11 tasks done
Tracked by #115

Expressions: Extend with more functionality #646

olemartinorg opened this issue Aug 12, 2022 · 3 comments
Labels
area/logic related to logic/dynamics/expressions feature-complete Features needed for parity with Altinn 2 (target: June 2023) org/brg Issues relevant for Brønnøysundregistrene. org/ssb Issues relevant for Statistisk sentralbyrå.

Comments

@olemartinorg
Copy link
Contributor

olemartinorg commented Aug 12, 2022

In the layout expressions project we have intentionally set the bar fairly low, in order to get to a basic implementation faster. As planned for the first release, layout expressions can only be used to evaluate to a boolean value. On the backend, only the hidden and required properties for layout components will be evaluated, while the frontend will evaluate other properties like readOnly and various properties in the edit properties for groups.

This issue tracks extensions to these expressions we've thought of, but won't necessarily arrive in the first version. These tasks should probably be extracted to separate issues when/if we start working on them, if the efforts to implement them are large enough.

  • Recursive layout expressions

Passing an expression as an argument to an expression can be useful for more advanced logic. If we're implementing this, adding functions for and and or (both with any amount of arguments) is a given. An example of a recursive expression:

{
  "hidden": ["and",
    ["component", "some-other-component"],
    ["or",
      ["dataModel", "MyModel.Path"],
      ["dataModel", "MyModel.Alternative.Path"],
      ["dataModel", "MyModel.Third.Alternative.Path"],
    ]
  ]
}
  • Expressions returning strings/non-booleans

We could also use expressions for conditionally swap out labels/texts in textResourceBindings, etc. If we do, there should probably also be function(s) to map known data model (etc) values to the appropriate text resource keys, handle the default case if no mapping is valid, etc. We should also implement functions like concat, toUpperCase, etc, for simple string manipulations. There would also be a use-case for the most basic function (possibly even implicit) where an argument is return verbatim (i.e. a lookup function):

{
  "textResourceBindings": {
    "title": "myTitle",
    "description": ["dataModel", "MyModel.Description"]
  }
}

We could possibly replace existing implementations for calculations with layout expressions as well. Care needs to be taken to ensure we don't restrict functionality in a way that makes it impossible to implement existing calculations that are already implemented in some apps - we'd like for a frictionless upgrade path to make use of layout expressions instead of RuleHandler.js.

Careful thought should go into designing this in a way that makes it easy (or at least possible) to implement calculations for rows in a repeating group (respecting potentially hidden/filtered rows). See discussion on Slack here. It should also be possible to implement a function for counting the number of rows in a repeating group.

One advantage to using expressions for calculation is automatic API support and possibly valdation to avoid client-side tampering (if implemented on the backend).

Example for a sum implementation:

{
  "id": "total",
  "type": "Input",
  "readOnly": true,
  "value": ["sum",
    ["component", "value1"],
    ["component", "value2"],
    ["component", "value3"]
  ]
}

Or concatenating strings to present a full name:

{
  "id": "fullName",
  "type": "Input",
  "readOnly": true,
  "value": ["concat",
    ["component", "lastName"],
    ", ",
    ["component", "firstName"]
  ]
}

This requires both validation (a boolean, in principle) and a validation message (a string, which could perform a lookup in text resources). We would also have to support soft validations. Consider if we should use a prefix like *WARNING* like we do today, or implement this using a custom not-just-string data type.

  • More argument types: Shadow fields (no need, shadow fields live inside the data model)

When we have an implementation for shadow fields, we should support lookup up those values.

Large expressions should be possible to re-use. Either by separating them out to definitions (similar to a structure like in JsonSchema) and referencing them from there, or by implementing functions to directly reference other expressions:

{
  "id": "dependsOnSomethingElse",
  "type": "Input",
  "hidden": ["isHidden", ["component", "someOtherComponent"]]
}

Or, more generically:

{
  "id": "dependsOnSomethingElse",
  "type": "Input",
  "hidden": [
    "equals",
    ["getProperty", ["component", "someOtherComponent"], "hidden"],
    true
  ]
}

A likely need/want is to use layout expressions to hide an entire repeating group row, possibly based on some data within it. This type of dynamic should be placed on the group component, and would in effect hide all components inside that row. It is an outstanding question if this should lead to the entire row being deleted when submitting the data, if this should not happen, or if it should be configurable.

See discussion on Slack

A much-discussed need is a function that allows you to check if a value is in a list of values. This is needed to assert if a certain checkbox has been checked, but as long as #273 is unsolved, this would also require support for comma-separated values. An alternative is creating a temporary function for this exact case (inCheckboxValue or inCommaSeparatedList).

See discussion on Slack

Shortcut function similar to equals, but compares the first argument against multiple others to check if the first argument matches either one of them.

See discussion on Slack

Function used to look up a text resource key, resolving to the value of it. This is not really that relevant for backend code, so perhaps we could limit this so it's only possible to use it in frontend-evaluated expressions.

Function used to look up the current language (nb, en, etc).

@xmrsa
Copy link

xmrsa commented Nov 10, 2022

It is important that the "hidden"-parameter also allows expressions like "contains" and "notContains" in addition to the existing "equals" and "notEquals". Please make sure that null-values can be allowed so you can add a new row to a repeating group without it disappearing. Every field in the new row is null until you write and save something there.

@olemartinorg olemartinorg mentioned this issue Feb 28, 2023
6 tasks
@FinnurO FinnurO added the org/brg Issues relevant for Brønnøysundregistrene. label Mar 9, 2023
@FinnurO FinnurO added the feature-complete Features needed for parity with Altinn 2 (target: June 2023) label Mar 31, 2023
@olemartinorg
Copy link
Contributor Author

@olemartinorg olemartinorg changed the title Layout expressions: Extend with more functionality Expressions: Extend with more functionality May 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/logic related to logic/dynamics/expressions feature-complete Features needed for parity with Altinn 2 (target: June 2023) org/brg Issues relevant for Brønnøysundregistrene. org/ssb Issues relevant for Statistisk sentralbyrå.
Projects
Archived in project
Status: Done
Archived in project
Development

No branches or pull requests

3 participants