From 96b4e1833183fa6c67ba2acacd1cb62d934d98c8 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 3 Dec 2024 15:33:00 +0100 Subject: [PATCH 01/31] Removing ancient and mostly irrelevant warning (for an older app-lib, with the older PDF generator) --- .../guides/development/options/_index.en.md | 23 ------------------- .../guides/development/options/_index.nb.md | 22 ------------------ 2 files changed, 45 deletions(-) diff --git a/content/altinn-studio/guides/development/options/_index.en.md b/content/altinn-studio/guides/development/options/_index.en.md index b574a6457e..e2c7d8907c 100644 --- a/content/altinn-studio/guides/development/options/_index.en.md +++ b/content/altinn-studio/guides/development/options/_index.en.md @@ -146,29 +146,6 @@ For nested groups follows the same pattern but with an additional index indicato For a complete example of how this is setup see our [demo app.](https://altinn.studio/repos/ttd/dynamic-options-rep) -{{%notice warning%}} - -**Applies to applications using version 7.4.0 or older of the nuget packages** - https://github.com/Altinn/app-lib-dotnet/release - -
- -During PDF-generation the app will try to call the same option endpoint as app-frontend does. -We currently have a weakness where mapping parameters not are included in this request, see issue [#7903.](https://github.com/Altinn/altinn-studio/issues/7903) - -A possible workaround here is to return an empty array when the PDF-generator asks for options with empty query params, example: - -```c# -string someArg = keyValuePairs.GetValueOrDefault("someArg"); -string someOtherArg = keyValuePairs.GetValueOrDefault("someOtherArg"); - -if (string.IsNullOrEmpty(someArg) || string.IsNullOrEmpty(someOtherArg)) { - return await Task.FromResult(new List()); -} -``` - -Notice that this wil result in the option value and not the label being present as the end users answer. -{{% /notice%}} - ### Store metadata for the parameters used to retrieve options in tha datamodel You can store metadata for the parameters used to retrieve options in the datamodel by setting the `metadata` property diff --git a/content/altinn-studio/guides/development/options/_index.nb.md b/content/altinn-studio/guides/development/options/_index.nb.md index bfc8d7834e..ee330060cd 100644 --- a/content/altinn-studio/guides/development/options/_index.nb.md +++ b/content/altinn-studio/guides/development/options/_index.nb.md @@ -139,28 +139,6 @@ For nøstede repeterende grupper vil man følge det samme mønsteret, men med en For et komplett eksempel kan du se vår [demo app.](https://altinn.studio/repos/ttd/dynamic-options-rep) -{{%notice warning%}} -**Gjelder applikasjoner som benytter versjon 7.4.0 eller eldre av nuget pakkene** - se https://github.com/Altinn/app-lib-dotnet/release - -
- -Under PDF-generering vil appen prøve å kalle det samme options-endepunktet som app-frontend gjør. -Vi har foreløpig en svakhet ved at eventuelle `mapping`-parametere ikke blir inkludert i denne forespørselen, se [sak #7903](https://github.com/Altinn/altinn-studio/issues/7903). - -En mulig workaround her er å returnere en tom array i det PDF-generatoren spør om options med tomme query-parametere, eksempel: - -```c# -string someArg = keyValuePairs.GetValueOrDefault("someArg"); -string someOtherArg = keyValuePairs.GetValueOrDefault("someOtherArg"); - -if (string.IsNullOrEmpty(someArg) || string.IsNullOrEmpty(someOtherArg)) { - return await Task.FromResult(new List()); -} -``` - -Merk at dette vil resultere i at PDF-filen vil vise kodeverdien og ikke visningsverdien som sluttbrukers svar. -{{% /notice%}} - ### Lagre metadata for parametrene som ble brukt til å hente options Du kan lagre metadata for parameterene som ble brukt til å hente kodeliste i datamodellen ved å sette egenskapen `metadata` From 0292ebdd2120285efd4a17d62ae5d2c08b2c51aa Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 3 Dec 2024 15:34:09 +0100 Subject: [PATCH 02/31] Removing ancient warning --- .../development/options/dynamic-codelists/_index.en.md | 6 ------ .../development/options/dynamic-codelists/_index.nb.md | 6 ------ 2 files changed, 12 deletions(-) diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md index f3e25663d8..a98e2b98a7 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md @@ -69,12 +69,6 @@ The interface has a property `Id`, which should be set to the optionId, and a me ### Secured dynamic options -{{%notice warning%}} - -**NOTICE:** to use this functionality the app must use version >= 4.27.0 of the nuget packages `Altinn.App.PlatformServices`, `Altinn.App.Common` and `Altinn.App.Api`. - -{{%/notice%}} - If you want to expose options that are sensitive you can use `IInstanceAppOptionsProvider`, which will validate that the user has read rights defined in the authorization policy defined in the app's `policy.xml`-file. Below you find an example of how to implement a secured custom options provider. The `IInstanceAppOptionsProvider` interface must be implemented, and a `secure`-prop must be added to the component. The following option will be exposed at `/{org}/{app}/instances/{instanceOwnerId}/{instanceGUID}/options/children`. diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md index a2dc1c4ccc..a615236cd4 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md @@ -69,12 +69,6 @@ Interfacene har en egenskap `Id`, som skal settes til til den id'en man skal sp ### Sikrede dynamiske kodelister -{{%notice warning%}} - -**MERK:** for å benytte denne funksjonaliteten må man versjon >= 4.27.0 av nugetpakkene `Altinn.App.PlatformServices`, `Altinn.App.Common` og `Altinn.App.Api`. - -{{%/notice%}} - Om du ønsker å eksponere kodelister som inneholder sensitive data som man ikke ønsker skal være tilgjengelige i et åpent API kan man benytte `IInstanceAppOptionsProvider`. Disse kodelistene validerer at brukeren har lesetilgang definert i applikasjonens `policy.xaml`-fil. Under finner du et eksempel på man setter opp en sikret kodeliste. Interfacet `IInstanceAppOptionsProvider` må implementeres og en `secure` boolean må legges på komponenten. Her vil man få ut den oppsatte kodelisten i det appen får et kall mot `/{org}/{app}/instances/{instanceOwnerId}/{instanceGUID}/options/children`. From fbf396f64c808bc69e2749cdfaac320e019f1587 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 3 Dec 2024 15:35:20 +0100 Subject: [PATCH 03/31] Removing reference to ancient code structure --- .../guides/development/options/dynamic-codelists/_index.en.md | 2 +- .../guides/development/options/dynamic-codelists/_index.nb.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md index a98e2b98a7..cd43513bd5 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md @@ -120,7 +120,7 @@ namespace Altinn.App.Core ``` -For your implementation to be picked up you need to add the following line in your `Startup.cs` (or `Program.cs` in .NET 6): +For your implementation to be picked up you need to add the following line in your `Program.cs`: ```csharp services.AddTransient(); diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md index a615236cd4..a49b03bb58 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md @@ -120,7 +120,7 @@ namespace Altinn.App.Core ``` -For at denne implementasjonen skal plukkes opp av applikasjonen må den registreres i `Startup.cs` (eller `Program.cs` i .NET 6): +For at denne implementasjonen skal plukkes opp av applikasjonen må den registreres i `Program.cs`: ```csharp services.AddTransient(); From 2d150685c2f31e195f9ea93d1ed94573278a72ce Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 3 Dec 2024 17:42:33 +0100 Subject: [PATCH 04/31] Improving the docs for dynamic code lists, and moving the sections about query parameters (they're not useful in any other contexts) --- .../guides/development/options/_index.en.md | 99 --------- .../guides/development/options/_index.nb.md | 95 -------- .../options/dynamic-codelists/_index.en.md | 202 ++++++++++++++---- .../options/dynamic-codelists/_index.nb.md | 201 +++++++++++++---- 4 files changed, 321 insertions(+), 276 deletions(-) diff --git a/content/altinn-studio/guides/development/options/_index.en.md b/content/altinn-studio/guides/development/options/_index.en.md index e2c7d8907c..da5fd198a4 100644 --- a/content/altinn-studio/guides/development/options/_index.en.md +++ b/content/altinn-studio/guides/development/options/_index.en.md @@ -47,105 +47,6 @@ This is performed by having a separate ``dataModelBindings`` with the key ``"lab } ``` - -## Pass query parameters when fetching options - -Options supports query parameters when making the api call, the parameter `language` is added automatically. - -### Pass static query parameters - -You can add static query parameters by setting the `queryParameters` property on the component: - -```json -{ - "id": "some-dropdown-component", - "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype" - }, - "required": true, - "optionsId": "loyvetyper", - "queryParameters": { - "loyvetype": "garanti" - } -}, -``` - -In the example above the parameter `?loyvetype=garanti` will be added to the request. - -### Pass dynamic query parameters based on the data model - -You can add dynamic parameters by setting the `mapping` property on the component: - -```json -{ - "id": "some-dropdown-component", - "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype" - }, - "required": true, - "optionsId": "loyvetyper", - "mapping": { - "soknad.transportorOrgnummer": "orgnummer" - } -}, -``` - -In the example above, the query parameter `orgnummer={nr}`, where `{nr}` is the value of `soknad.transportorOrgnummer` -will be set. -If an option is setup with mapping and the given data field changes app-frontend will refetch the option. This can be -used to dynamically decide which choices are available based on information given by the end user. - -Passing query parameters from repeating groups is also supported by adding an index indicator for the relevant indexes. -Example for a group: - -```json -{ - "id": "dropdown-group", - "type": "Dropdown", - "textResourceBindings": { - "title": "Select city" - }, - "dataModelBindings": { - "simpleBinding": "Group.City" - }, - "required": true, - "optionsId": "cities", - "mapping": { - "Group[{0}].Country": "country" - } -}, -``` - -For nested groups follows the same pattern but with an additional index indicator for the nested group: - -```json -{ - "id": "dropdown-nested-group", - "type": "Dropdown", - "textResourceBindings": { - "title": "Select city" - }, - "dataModelBindings": { - "simpleBinding": "Group.SubGroup.City" - }, - "required": true, - "optionsId": "cities", - "mapping": { - "Group[{0}].SubGroup[{1}].Country": "country" - } -}, -``` - -For a complete example of how this is setup see our [demo app.](https://altinn.studio/repos/ttd/dynamic-options-rep) - ### Store metadata for the parameters used to retrieve options in tha datamodel You can store metadata for the parameters used to retrieve options in the datamodel by setting the `metadata` property diff --git a/content/altinn-studio/guides/development/options/_index.nb.md b/content/altinn-studio/guides/development/options/_index.nb.md index ee330060cd..19d6c567ee 100644 --- a/content/altinn-studio/guides/development/options/_index.nb.md +++ b/content/altinn-studio/guides/development/options/_index.nb.md @@ -44,101 +44,6 @@ Dette gjøres ved å ha en egen ``dataModelBindings`` med navnet ``"label":`` i } ``` -## Sende med spørringsparametere ved henting av en kodeliste - -Kodelisteendepunktet støtter spørringsparametre. Parameteren `language` sendes med automatisk. - -### Sende med statiske parametre - -Man kan legge til statiske parametre ved å sette opp `queryParameters` på den aktuelle komponenten: - -```json -{ - "id": "dropdown-komponent", - "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype" - }, - "required": true, - "optionsId": "loyvetyper", - "queryParameters": { - "loyvetype": "garanti" - } -} -``` - -I eksempelet over vil parameteren `?loyvetype=garanti` bli sendt med i kallet. - -### Sende med dynamiske parametre basert på datamodellen - -Man kan legge til dynamiske parametre ved å sette opp `mapping` på den aktuelle komponenten: - -```json -{ - "id": "dropdown-komponent", - "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype" - }, - "required": true, - "optionsId": "loyvetyper", - "mapping": { - "soknad.transportorOrgnummer": "orgnummer" - } -} -``` - -I eksempelet over vil parameteren `orgnummer={nr}` bli sendt med. `{nr}` er verdien på feltet `soknad.transportorOrgnummer`. -Om man setter opp en kobling til et datafelt og dette feltet endrer seg, så vil appen hente kodelisten på nytt. På denne måten kan man dynamisk styre hvilke valg som vises basert på informasjon gitt av sluttbruker. - -Å sende med parametere fra repeterende grupper gjøres ved å legge ved en indeks-indikator for de relevante gruppene. Eksempel: - -```json -{ - "id": "dropdown-group", - "type": "Dropdown", - "textResourceBindings": { - "title": "Select city" - }, - "dataModelBindings": { - "simpleBinding": "Group.City" - }, - "required": true, - "optionsId": "cities", - "mapping": { - "Group[{0}].Country": "country" - } -} -``` - -For nøstede repeterende grupper vil man følge det samme mønsteret, men med en ekstra indikator for den nøstede gruppa: - -```json -{ - "id": "dropdown-nested-group", - "type": "Dropdown", - "textResourceBindings": { - "title": "Select city" - }, - "dataModelBindings": { - "simpleBinding": "Group.SubGroup.City" - }, - "required": true, - "optionsId": "cities", - "mapping": { - "Group[{0}].SubGroup[{1}].Country": "country" - } -} -``` - -For et komplett eksempel kan du se vår [demo app.](https://altinn.studio/repos/ttd/dynamic-options-rep) - ### Lagre metadata for parametrene som ble brukt til å hente options Du kan lagre metadata for parameterene som ble brukt til å hente kodeliste i datamodellen ved å sette egenskapen `metadata` diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md index cd43513bd5..82dd14639c 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md @@ -1,20 +1,17 @@ --- title: Dynamic code lists generated runtime linktitle: Dynamic code lists -description: How to create dynamic code lists created during runtime execution of the application? toc: false weight: 100 --- -As an alternative to the static files you can have code that determines what the lists should be during runtime. This makes it possible to expose dynamic values that for instance are filtered or looked up in external sources. Dynamic code lists can either be open and accessible to all or secured and limited to those with read access to the instance. +In an Altinn 3 app you can also have dynamic code lists that are generated runtime. This makes it possible to have dynamic lists that are filtered or looked up in external sources. Dynamic code lists can either be public (accessible to all, without authentication), or secured and limited to those with read access to the instance. -In versions prior to 4.24.0 this was done by overriding the `GetOptions` method in `App.cs`. This method is now deprecated and is replaced by putting the option code in separate classes implementing an interface and registering the implementation in the application dependency injection container. This allows for better separation, inject dependencies into the constructor, pass in language and other query parameters and generally handle all aspects of the implementation as you see fit. +For public code lists, implement the `IAppOptionsProvider` interface, while for secured code lists, implement the `IInstanceAppOptionsProvider`. The approach is the same for both, and the model returned is the same. The implementation is kept separate to avoid exposing values that should be secured. -For code lists that are open you implement the `IAppOptionsProvider` interface and for code lists that should be secured you implement the `IInstanceAppOptionsProvider` interface. The pattern is the same for both, and the models returned is the same, but the implementation is kept separate to avoid exposing data that should be secured. +### Public code lists -### Open dynamic code lists - -Below you find an example of how to implement a open custom options provider. The url will will still be exposed from the same endpoint as before `{org}/{app}/api/options/countires`. +Below you find an example of how to implement a public options provider. ```C# using Altinn.App.Common.Models; @@ -51,27 +48,34 @@ namespace Altinn.App.Core } } } - ``` -For your implementation to be picked up you need to add the following line in your `Startup.cs` (or `Program.cs` in .NET 6): +For your implementation to be picked up you need to add the following line in your `Program.cs`: -```csharp +```C# services.AddTransient(); ``` -Note that you can have multiple registrations of this interface. The correct implementation is resolved by finding the one with the correct id. - -The interface has a property `Id`, which should be set to the optionId, and a method `GetAppOptionsAsync` for resolving the options. This method accepts a language code and a dictionary of key/value pairs. Both parameters will typically be query parameters picked up from the controller and passed in. Although language could be put in the dictionary as well it's decided to be explicit on this particular parameter. +The result of this implementation will be available at the endpoint `{org}/{app}/api/options/countries`. The identifier can be used in components, so to use the code list in a Dropdown component you can set `optionsId` as in the following example: -> Language codes should be based on ISO 639-1 or the W3C IANA Language Subtag Registry. The latter is built upon the ISO 639-1 standard but is guaranties uniques of the codes, where as ISO 639-1 have conflicting usage for some codes. -> +```json {hl_lines=[10]} +{ + "id": "dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "Some title" + }, + "dataModelBindings": { + "simpleBinding": "some.field" + }, + "optionsId": "countries" +} +``` -### Secured dynamic options +### Secured options -If you want to expose options that are sensitive you can use `IInstanceAppOptionsProvider`, which will validate that the user has read rights defined in the authorization policy defined in the app's `policy.xml`-file. -Below you find an example of how to implement a secured custom options provider. The `IInstanceAppOptionsProvider` interface must be implemented, and a `secure`-prop must be added to the component. -The following option will be exposed at `/{org}/{app}/instances/{instanceOwnerId}/{instanceGUID}/options/children`. +If you want to produce lists of options that are sensitive you can implement `IInstanceAppOptionsProvider`, which will validate that the user has read rights as defined in the authorization policy from the `policy.xml`-file. +Below you'll find an example of how to implement a secured options provider. ```C# using System.Collections.Generic; @@ -126,25 +130,141 @@ For your implementation to be picked up you need to add the following line in yo services.AddTransient(); ``` -Note that you can have multiple registrations of this interface. The correct implementation is resolved by finding the one with the correct id. - -The interface has a property `Id`, which should be set to the optionId, and a method `GetInstanceAppOptionsAsync` for resolving the options. This method accepts a language code and a dictionary of key/value pairs. Both parameters will typically be query parameters picked up from the controller and passed in. Although language could be put in the dictionary as well it's decided to be explicit on this particular parameter. These parameters are the same as for the open variant of options, in addition the instance id (which identifies both the instance owner and the instance itself) will be passed in. - -The final configuration needed is the `secure`-boolean on the component. Example: - -```json {hl_lines=[13]} - { - "id": "dropdown-component", - "type": "Dropdown", - "textResourceBindings": { - "title": "Some title", - "description": "Some description" - }, - "dataModelBindings": { - "simpleBinding": "some.field" - }, - "required": true, - "optionsId": "children", - "secure": true - } -``` \ No newline at end of file +The result of this implementation will be available at the endpoint `{org}/{app}/instances/{instanceOwnerId}/{instanceGUID}/options/children`. The identifier can be used in components, so to use the code list in a Dropdown component you can set `optionsId` as in the following example. It is also important to set the `secure` property to `true` to indicate that this is a secured code list. + +```json {hl_lines=["10-11"]} +{ + "id": "dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "Some title" + }, + "dataModelBindings": { + "simpleBinding": "some.field" + }, + "optionsId": "children", + "secure": true +} +``` + +## Query parameters + +The options endpoint you create supports query parameters. The `language` parameter is sent automatically, and other parameters can be sent from the component configuration. These can be read from the `keyValuePairs` parameter in the implementation. This can be useful to filter the code list based on data in the data model, or in other ways vary the code list based on context. + +As an example, consider a form with two `Dropdown` components that are linked together. The first lets the user choose a county, and the second lets the user choose a municipality. The municipalities shown in the second component should be filtered based on the county selected in the first component. This can be solved by sending the county as a query parameter to the code list for municipalities (and then filter the list based on this parameter in your implementation). + +### Based on expressions + +{{%notice info%}} +Query parameters based on expressions are available from app-frontend version 4.9.0 or higher. If your app is using the rolling release of major version 4, this is already available. +{{% /notice%}} + +You can add both static and dynamic parameters by setting up `queryParameters` on the component: + +```json {hl_lines=["12-16"]} +{ + "id": "dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "Some title" + }, + "dataModelBindings": { + "simpleBinding": "some.field" + }, + "optionsId": "countries", + "queryParameters": { + "country": "norway", + "orgnumber": ["dataModel", "some.orgnumber"], + "adult": ["greaterThanEq", ["dataModel", "some.age"], 18] + } +} +``` + +In the example above the parameter `country=norway` will always be added to the request (this is entirely static and will not change). The parameter `orgnumber={nr}` will be added, where `{nr}` is the value of the field `some.orgnumber` in the data model. The parameter `adult={bool}` will be added, where `{bool}` will be either `true` or `false` based on whether the value of the field `some.age` is greater than or equal to 18. + +More examples of expressions can be found in the [dynamics documentation](../../dynamics), and the full list of available functions can be found in the [expression reference overview](../../../../reference/logic/expressions). + +### Based on the data model + +{{%notice warning%}} +This approach is discouraged. From app-frontend version 4.9.0, it is possible to use the `queryParameters` property instead. As described above, this property allows you to add both static and dynamic query parameters using expressions, making them more flexible than `mapping`. + +At some point, the `mapping` property will be removed, but when that happens tools will be provided to migrate existing configurations to use `queryParameters` instead. +{{% /notice%}} + +You can add dynamic parameters by setting the `mapping` property on the component: + +```json +{ + "id": "some-dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "NyGarantiLoyvetype" + }, + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype" + }, + "required": true, + "optionsId": "loyvetyper", + "mapping": { + "soknad.transportorOrgnummer": "orgnummer" + } +} +``` + +In the example above, the query parameter `orgnummer={nr}`, where `{nr}` is the value of `soknad.transportorOrgnummer` +will be set. +If an option is setup with mapping and the given data field changes app-frontend will refetch the option. This can be +used to dynamically decide which choices are available based on information given by the end user. + +Passing query parameters from repeating groups is also supported by adding an index indicator for the relevant indexes. +Example for a group: + +```json +{ + "id": "dropdown-group", + "type": "Dropdown", + "textResourceBindings": { + "title": "Select city" + }, + "dataModelBindings": { + "simpleBinding": "Group.City" + }, + "required": true, + "optionsId": "cities", + "mapping": { + "Group[{0}].Country": "country" + } +}, +``` + +For nested groups follows the same pattern but with an additional index indicator for the nested group: + +```json +{ + "id": "dropdown-nested-group", + "type": "Dropdown", + "textResourceBindings": { + "title": "Select city" + }, + "dataModelBindings": { + "simpleBinding": "Group.SubGroup.City" + }, + "required": true, + "optionsId": "cities", + "mapping": { + "Group[{0}].SubGroup[{1}].Country": "country" + } +}, +``` + +For a complete example of how this is setup see our [demo app.](https://altinn.studio/repos/ttd/dynamic-options-rep) + +## Things to consider + +- The method `GetAppOptionsAsync` receives a language code in the `language` parameter. Language codes are based on ISO 639-1 or the W3C IANA Language Subtag Registry. The latter is built upon the ISO 639-1 standard but is guaranties uniques of the codes, whereas ISO 639-1 have conflicting usage for some codes. +- An app can have many implementations of these interfaces, one for each option list. The correct implementation is found by looking at the code list identifier that is requested, and comparing it to the `Id` property in the implementation. This is also the identifier used in the `optionsId` property in the component configuration. Therefore, the `Id` property in the implementation must be unique per app. +- It may be tempting to implement a dynamic option list that fetches data from the data model and produces the option list based on this. This is not recommended, as the app frontend only fetches the option list once for each unique set of query parameters. This means that the user interface showing the option list will not update in line with changes in the data model. + - An alternative is to use the functionality for [dynamic code lists based on the data model](../repeating-group-codelists), in some cases together with corresponding code in [DataProcessor](../../dynamics/data-processing). + - Another alternative may be to use query parameters, as described above. +- If you use query parameters, it may be wise to consider how many unique combinations of parameters will typically be used in the app. If there are many, consider using a different approach such as fetching all data and filtering valid values in the frontend using [`optionFilter`](../filtering). Many different combinations of query parameters can lead to the app having to do a lot of unnecessary work to fetch new option lists every time the user makes a change in the form. diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md index a49b03bb58..4b735d7785 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md @@ -1,20 +1,17 @@ --- title: Dynamiske kodelister generert under kjøring av applikasjonen linktitle: Dynamiske kodelister -description: Hvordan lage dynamiske kodelister som bygges opp når applikasjonen kjører? toc: false weight: 100 --- -I app-templaten har man også mulighet til å ha dynamisk kodelister som bestemmes under kjøringen av appen. Dette muligjør det å eksponere dynamiske verdier som kan filtreres eller hentes fra andre kilder. Dynamiske kodelister kan enten være åpne, dvs. alle brukere når de, eller de kan være sikret gjennom at du må ha tilgang til instansen for å se de. +I en Altinn 3 app har man også mulighet til å ha dynamisk kodelister som produseres dynamisk ved kjøring av appen. Dette gjør det mulig å lage dynamiske verdier, for eksempel ved å hente og filtrere verdier fra andre kilder. Dynamiske kodelister kan enten være åpne (tilgjengelig for alle, uten autentisering), eller sikret slik at brukeren må ha tilgang til instansen for å hente kodelisten. -I versjoner eldre enn 4.24.0 ble dette gjort ved å legge til kode i metoden `GetOptions` i `App.cs`. Denne metoden er nå erstattet ved at man legger til egne klasser for hver kodeliste som implementerer et interface og at man registrerer denne i applikasjonen sin 'dependency injection cointainer'. Dette gir bedre skille mellom de ulike kodelistene, muliggjør å sende avhengigheter inn i konstruktøren til klassen, sende inn språk og andre parametere og generelt håndtere alle aspekter av implementeringen slik du selv ønsker det. +For åpne kodelister implementerer man `IAppOptionsProvider` interfacet, mens for sikrede kodelister implementerer man `IInstanceAppOptionsProvider`. Fremgangsmåten er den samme for begge og modellen som returneres er lik. Implementeringen holdes adskilt for ikke å eksponere verdier som skulle vært sikret. -For kodelister som er åpne implementerer man `IAppOptionsProvider` interfacet, mens for kodelister som skal være sikret implementerer man `IInstanceAppOptionsProvider`. Fremgangsmåten er den samme for begge to og modellen som returneres er lik. Men implementeringen holdes adskilt for ikke å eksponere verdier som skulle vært sikret. +## Åpne kodelister -### Åpne dynamiske kodelister - -Under finner du et eksempel på hvordan dette kan settes opp for en åpen kodeliste. Her vil man få ut den oppsatte kodelisten i det appen får et kall mot `{org}/{app}/api/options/countries`. +Under finner du et eksempel på hvordan dette kan settes opp for en åpen kodeliste. ```C# using Altinn.App.Common.Models; @@ -51,27 +48,34 @@ namespace Altinn.App.Core } } } - ``` -For at denne implementasjonen skal plukkes opp av applikasjonen må den registreres i `Startup.cs` (eller `Program.cs` i .NET 6): +For at denne implementasjonen skal plukkes opp av applikasjonen må den registreres i `Program.cs`: -```csharp +```C# services.AddTransient(); ``` -Legg merke til at du kan ha mange implementasjoner av dette interfacet. Den rette implementasjonen finnes gjennom å se på hvilken kodeliste id det spørres etter. - -Interfacene har en egenskap `Id`, som skal settes til til den id'en man skal spørre etter, og en metode `GetAppOptionsAsync` som returnerer selve kodelisten. Denne metoden tar i mot språk og en liste med key/value par som typisk er query parametre som plukkes opp av kontrolleren og sendes inn. Selv om språk kunne vært et key/value par og sånn sett hvert i listen, så er denne lagt utenfor for å være eksplisitt på språk. +Resultatet av denne implementasjonen vil bli tilgjengeleg på endepunktet `{org}/{app}/api/options/countries`. Identifikatoren kan brukes i komponenter, så for å bruke kodelisten i en Dropdown-komponent kan man sette `optionsId` som i følgende eksempel: -> Språkkoder bør baseres på ISO 639-1 standarden eller W3C IANA Language Subtag Registry standarden. Sistnevnte bygger på ISO 639-1 standarden men garanterer at alle kodene er unike, noe ISO 639-1 ikke gjør. -> +```json {hl_lines=[10]} +{ + "id": "dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "Some title" + }, + "dataModelBindings": { + "simpleBinding": "some.field" + }, + "optionsId": "countries" +} +``` -### Sikrede dynamiske kodelister +## Sikrede kodelister -Om du ønsker å eksponere kodelister som inneholder sensitive data som man ikke ønsker skal være tilgjengelige i et åpent API kan man benytte `IInstanceAppOptionsProvider`. Disse kodelistene validerer at brukeren har lesetilgang definert i applikasjonens `policy.xaml`-fil. -Under finner du et eksempel på man setter opp en sikret kodeliste. Interfacet `IInstanceAppOptionsProvider` må implementeres og en `secure` boolean må legges på komponenten. -Her vil man få ut den oppsatte kodelisten i det appen får et kall mot `/{org}/{app}/instances/{instanceOwnerId}/{instanceGUID}/options/children`. +Om du ønsker å produsere kodelister som inneholder sensitive data som ikke skal være tilgjengelige i et åpent API kan man implementere `IInstanceAppOptionsProvider`. Slike sikrede kodelister kontrollerer at brukeren har lesetilgang som definert i applikasjonens `policy.xaml`-fil før brukeren kan hente innholdet i kodelisten. +Under finner du et eksempel på hvordan man setter opp en sikret kodeliste. ```C# using System.Collections.Generic; @@ -122,29 +126,144 @@ namespace Altinn.App.Core For at denne implementasjonen skal plukkes opp av applikasjonen må den registreres i `Program.cs`: -```csharp +```C# services.AddTransient(); ``` -Legg merke til at du kan ha mange implementasjoner av dette interfacet. Den rette implementasjonen finnes gjennom å se på hvilken kodeliste id det spørres etter. - -Interfacene har en egenskap `Id`, som skal settes til til den id'en man skal spørre etter, og en metode `GetAppOptionsAsync` som returnerer selve kodelisten. Denne metoden tar i mot språk og en liste med key/value par som typisk er query parametre som plukkes opp av kontrolleren og sendes inn. Selv om språk kunne vært et key/value par og sånn sett hvert i listen, så er denne lagt utenfor for å være eksplisitt på språk. - -Siste konfigurasjon som trengs er å legge til `secure`-boolean på den aktuelle komponenten. Eksempel: - -```json {hl_lines=[13]} - { - "id": "dropdown-component", - "type": "Dropdown", - "textResourceBindings": { - "title": "Some title", - "description": "Some description" - }, - "dataModelBindings": { - "simpleBinding": "some.field" - }, - "required": true, - "optionsId": "children", - "secure": true - } +Resultatet av denne implementasjonen vil bli tilgjengeleg på endepunktet `{org}/{app}/instances/{instanceOwnerId}/{instanceGUID}/options/children`. Identifikatoren kan brukes i komponenter, så for å bruke kodelisten i en Dropdown-komponent kan man sette `optionsId` som i følgende eksempel. Det er også viktig å sette `secure`-egenskapen til `true` for å indikere at dette er en sikret kodeliste. + +```json {hl_lines=["10-11"]} +{ + "id": "dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "Some title" + }, + "dataModelBindings": { + "simpleBinding": "some.field" + }, + "optionsId": "children", + "secure": true +} +``` + +## Spørringsparametre + +Kodeliste-endepunktet du lager støtter spørringsparametre. Parameteren `language` sendes med automatisk, og andre parametre kan sendes med fra komponentkonfigurasjonen. Disse kan du lese ut fra `keyValuePairs`-parameteren i implementasjonen. Dette kan være nyttig for å filtrere kodelisten basert på data i datamodellen, eller på andre måter variere kodelisten basert på kontekst. + +Som et eksempel kan vi se for oss et skjema med to `Dropdown`-komponenter som er knyttet sammen. Den første lar brukeren velge et fylke, og den andre lar brukeren velge en kommune. Kommunene som vises i den andre komponenten skal være filtrert basert på fylket som er valgt i den første komponenten. Dette kan løses ved å sende med fylket som et spørringsparameter til kodelisten for kommuner. + +### Basert på uttrykk + +{{%notice info%}} +Dynamiske parametre basert på uttrykk er tilgjengelig fra app-frontend versjon 4.9.0 eller høyere. Hvis appen din bruker den rullerende utgivelsen av hovedversjon 4, er dette allerede tilgjengelig. +{{% /notice%}} + +Man kan legge til både statiske og dynamiske parametre ved å sette opp `queryParameters` på den aktuelle komponenten: + +```json {hl_lines=["12-16"]} +{ + "id": "dropdown-komponent", + "type": "Dropdown", + "textResourceBindings": { + "title": "NyGarantiLoyvetype" + }, + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype" + }, + "required": true, + "optionsId": "loyvetyper", + "queryParameters": { + "loyvetype": "garanti", + "orgnummer": ["dataModel", "soknad.transportorOrgnummer"], + "myndig": ["greaterThanEq", ["dataModel", "soknad.alder"], 18] + } +} ``` + +I eksempelet over vil parameteret `loyvetype=garanti` alltid bli sendt med (dette er helt statisk og vil ikke endre seg). Parameteret `orgnummer={nr}` vil bli sendt med, hvor `{nr}` er verdien på feltet `soknad.transportorOrgnummer` i datamodellen. Parameteret `myndig={bool}` vil bli sendt med, hvor `{bool}` blir enten `true` eller `false` basert på om verdien på feltet `soknad.alder` er større enn eller lik 18. + +Flere eksempler på uttrykk finner du i [dokumentasjonen for dynamikk](../../dynamics), og den fullstendige oversikten over tilgjengelige funksjoner finner du i [referanseoversikten over uttrykk](../../../../reference/logic/expressions). + +### Basert på datamodellen + +{{%notice warning%}} +Denne tilnærmingen frarådes. Fra og med app-frontend versjon 4.9.0 er det mulig å bruke `queryParameters`-egenskapen i stedet. Som beskrevet ovenfor, tillater denne egenskapen deg å legge til både statiske og dynamiske spørringsparametre ved hjelp av uttrykk - noe som gjør dem mer fleksible enn `mapping`. + +På et tidspunkt vil `mapping`-egenskapen bli fjernet, men når det skjer vil verktøy bli gitt for å migrere eksisterende konfigurasjoner til å bruke `queryParameters` i stedet. +{{% /notice%}} + +Man kan legge til dynamiske parametre ved å sette opp `mapping` på den aktuelle komponenten: + +```json +{ + "id": "dropdown-komponent", + "type": "Dropdown", + "textResourceBindings": { + "title": "NyGarantiLoyvetype" + }, + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype" + }, + "required": true, + "optionsId": "loyvetyper", + "mapping": { + "soknad.transportorOrgnummer": "orgnummer" + } +} +``` + +I eksempelet over vil parameteren `orgnummer={nr}` bli sendt med. `{nr}` er verdien på feltet `soknad.transportorOrgnummer`. +Om man setter opp en kobling til et datafelt og dette feltet endrer seg, så vil appen hente kodelisten på nytt. På denne måten kan man dynamisk styre hvilke valg som vises basert på informasjon gitt av sluttbruker. + +Å sende med parametre fra repeterende grupper gjøres ved å legge ved en indeks-indikator for de relevante gruppene. Eksempel: + +```json +{ + "id": "dropdown-group", + "type": "Dropdown", + "textResourceBindings": { + "title": "Select city" + }, + "dataModelBindings": { + "simpleBinding": "Group.City" + }, + "required": true, + "optionsId": "cities", + "mapping": { + "Group[{0}].Country": "country" + } +} +``` + +For nøstede repeterende grupper vil man følge det samme mønsteret, men med en ekstra indikator for den nøstede gruppa: + +```json +{ + "id": "dropdown-nested-group", + "type": "Dropdown", + "textResourceBindings": { + "title": "Select city" + }, + "dataModelBindings": { + "simpleBinding": "Group.SubGroup.City" + }, + "required": true, + "optionsId": "cities", + "mapping": { + "Group[{0}].SubGroup[{1}].Country": "country" + } +} +``` + +For et komplett eksempel kan du se vår [demo app.](https://altinn.studio/repos/ttd/dynamic-options-rep) + + +## Lurt å tenke på + +- Metoden `GetAppOptionsAsync` får inn en språkkode i parameteren `language`. Språkkoder bør baseres på ISO 639-1 standarden eller W3C IANA Language Subtag Registry standarden. Sistnevnte bygger på ISO 639-1 standarden men garanterer at alle kodene er unike, noe ISO 639-1 ikke gjør. +- En app kan ha mange implementasjoner av disse interfacene, en for hver kodeliste. Den rette implementasjonen finnes gjennom å se på hvilken kodeliste-identifikator det spørres etter, og sammenlignes med `Id`-egenskapen i implementasjonen. Dette er også identifikatoren som brukes i `optionsId`-egenskapen i komponentkonfigurasjonen. Dermed må også `Id`-egenskapen i implementasjonen være unik per app. +- Det kan være fristende å sette opp en dynamisk og sikret kodeliste hvor man henter ut data fra datamodellen og produserer kodelisten basert på dette. Dette er ikke anbefalt, da appens frontend bare henter kodelisten en gang hvor hvert unike sett med spørringsparametere. Det betyr at visningen av kodelisten ikke vil oppdatere seg i tråd med endringene i datamodellen. + - Et alternativ er å bruke funksjonaliteten for [dynamiske kodelister basert på datamodell](../repeating-group-codelists), i noen tilfeller sammen med tilsvarende kode i [DataProcessor](../../dynamics/data-processing). + - Et annet alternativ kan være å bruke spørringsparametre, som beskrevet over. +- Dersom man bruker spørringsparametre, kan det være lurt å tenke gjennom hvor mange unike kombinasjoner av parametre som typisk vil bli brukt i appen. Hvis det er mange, kan det være lurt å vurdere å bruke en annen tilnærming, som for eksempel å hente ut all data og filtrere gyldige verdier i frontend ved hjelp av [`optionFilter`](../filtering). Mange ulike kombinasjoner av spørringsparametre kan før til at appen må gjøre mye unødvendig arbeid for å hente nye kodeliste-verdier hver gang brukeren gjør en endring i skjemaet. \ No newline at end of file From 0c9f9f48144058f7b64befd0553604075089ceaa Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 3 Dec 2024 17:45:10 +0100 Subject: [PATCH 05/31] Adding a section about static code lists defined in the component config --- .../options/static-codelists/_index.en.md | 58 +++++++++++++++++-- .../options/static-codelists/_index.nb.md | 56 +++++++++++++++++- 2 files changed, 107 insertions(+), 7 deletions(-) diff --git a/content/altinn-studio/guides/development/options/static-codelists/_index.en.md b/content/altinn-studio/guides/development/options/static-codelists/_index.en.md index cdc2c69842..9c5f7362cc 100644 --- a/content/altinn-studio/guides/development/options/static-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/static-codelists/_index.en.md @@ -1,11 +1,47 @@ --- -title: Static code lists from the application repository -linktitle: Static code lists -description: How to configure static code lists from the application repository. +title: Static code lists toc: false weight: 50 --- +For simpler use-cases, a static code list is easy to configure. These can either be set directly in the component +configuration or in a json file in the application repository. Which method to use depends on the re-usability of +the code list. If multiple components should use the same code list, it is recommended to use the json file method. + +## Static code lists based on component configuration + +In the example configuration, a Dropdown component is set up with a static code list. The `options` property is an +array of objects, where each object represents a code list item. The `value` property is the value that will be +saved in the data model when the user selects the item. The `label` property is the text that will be displayed to +the user. + +```json {hl_lines=["8-21"]} +{ + "id": "some-dropdown-component", + "type": "Dropdown", + "textResourceBindings": {}, + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype" + }, + "options": [ + { + "value": "1", + "label": "Type 1" + }, + { + "value": "2", + "label": "Type 2" + }, + { + "value": "3", + "label": "Type 3" + } + ] +} +``` + +## Static code lists based on json files + By adding json based option files in the application repository, the application will automatically read the file and expose it through the options api. For this to work, the files must be placed in the `App/options/` folder and be named according to the following conventions `{optionId}.json` for the application to recognize them. For example if you have a list of countries in a file named `countries.json`, the optionId would be `countries`, and would be exposed through the api at `{org}/{app}/api/options/countries`. The static code lists should be in a special format as shown below: @@ -27,4 +63,18 @@ For example if you have a list of countries in a file named `countries.json`, th ] ``` -Note that the `label` field can be a key to a text resource (as shown above for sweden) or plain text. \ No newline at end of file +Note that the `label` field can be a key to a text resource (as shown above for sweden) or plain text. + +In order to reference this code list in a component, you can use the `optionsId` property in the component configuration: + +```json {hl_lines=["8"]} +{ + "id": "some-dropdown-component", + "type": "Dropdown", + "textResourceBindings": {}, + "dataModelBindings": { + "simpleBinding": "soknad.opphavsland" + }, + "optionsId": "countries" +} +``` \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/static-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/static-codelists/_index.nb.md index 2f95579bee..ab4d446ffb 100644 --- a/content/altinn-studio/guides/development/options/static-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/static-codelists/_index.nb.md @@ -1,11 +1,47 @@ --- -title: Statiske kodelister fra applikasjon -linktitle: Statiske kodelister -description: Hvordan konfigurere statiske kodelister levert fra applikasjonen? +title: Statiske kodelister toc: false weight: 50 --- +For enklere brukstilfeller er statiske kodelister det letteste å sette opp. Disse kan enten settes direkte +i komponentkonfigurasjonen eller i en json-fil i app-repositoriet. Hvilken metode som bør brukes avhenger av +gjenbruksbehovet til kodelisten. Hvis flere komponenter skal bruke samme kodeliste, anbefales det å +bruke metoden med json-filen. + +## Statiske kodelister basert på komponentkonfigurasjon + +I denne eksempelkonfigurasjonen er en Dropdown-komponent satt opp med en statisk kodeliste. Egenskapen `options` er en +array av objekter, hvor hvert objekt representerer et kodelisteelement. Egenskapen `value` er verdien som vil bli +lagret i datamodellen når brukeren velger elementet. Egenskapen `label` er teksten som vil bli vist til brukeren. + +```json {hl_lines=["8-21"]} +{ + "id": "some-dropdown-component", + "type": "Dropdown", + "textResourceBindings": {}, + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype" + }, + "options": [ + { + "value": "1", + "label": "Type 1" + }, + { + "value": "2", + "label": "Type 2" + }, + { + "value": "3", + "label": "Type 3" + } + ] +} +``` + +## Statiske kodelister basert på json-filer + Ved å legge json-lister i options mappen i app repo vil appen automatisk lese denne filen og eksponere det gjennom options-apiet. Options filene må ligge under `App/options/` og vil bli differensiert ved hjelp av navngivningen på json-filen. F.eks `land.json`. Her vil da optionsId være `land`, og vil være eksponert gjennom endepunktet `{org}/{app}/api/options/land`. Kodelistene må være på et spesifikt format. Eksempel på en kodeliste som inneholder land (`App/options/land.json`): @@ -28,3 +64,17 @@ Kodelistene må være på et spesifikt format. Eksempel på en kodeliste som inn ``` `label` feltet kan inneholde en tekstnøkkel til teskstressursene eller ren tekst. + +For å referere til denne kodelisten i en komponent, kan du bruke egenskapen `optionsId` i komponentkonfigurasjonen: + +```json {hl_lines=["8"]} +{ + "id": "some-dropdown-component", + "type": "Dropdown", + "textResourceBindings": {}, + "dataModelBindings": { + "simpleBinding": "soknad.opphavsland" + }, + "optionsId": "land" +} +``` \ No newline at end of file From f39525f329c74ad6374c9575eb8b1c614de06e5f Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 09:43:36 +0100 Subject: [PATCH 06/31] Better highlighting --- .../options/dynamic-codelists/_index.en.md | 12 ++++++------ .../options/dynamic-codelists/_index.nb.md | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md index 82dd14639c..150277fccd 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md @@ -161,7 +161,7 @@ Query parameters based on expressions are available from app-frontend version 4. You can add both static and dynamic parameters by setting up `queryParameters` on the component: -```json {hl_lines=["12-16"]} +```json {hl_lines=["11-15"]} { "id": "dropdown-component", "type": "Dropdown", @@ -194,7 +194,7 @@ At some point, the `mapping` property will be removed, but when that happens too You can add dynamic parameters by setting the `mapping` property on the component: -```json +```json {hl_lines=["12-14"]} { "id": "some-dropdown-component", "type": "Dropdown", @@ -220,7 +220,7 @@ used to dynamically decide which choices are available based on information give Passing query parameters from repeating groups is also supported by adding an index indicator for the relevant indexes. Example for a group: -```json +```json {hl_lines=[13]} { "id": "dropdown-group", "type": "Dropdown", @@ -235,12 +235,12 @@ Example for a group: "mapping": { "Group[{0}].Country": "country" } -}, +} ``` For nested groups follows the same pattern but with an additional index indicator for the nested group: -```json +```json {hl_lines=[13]} { "id": "dropdown-nested-group", "type": "Dropdown", @@ -255,7 +255,7 @@ For nested groups follows the same pattern but with an additional index indicato "mapping": { "Group[{0}].SubGroup[{1}].Country": "country" } -}, +} ``` For a complete example of how this is setup see our [demo app.](https://altinn.studio/repos/ttd/dynamic-options-rep) diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md index 4b735d7785..1238a6bf2c 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md @@ -195,7 +195,7 @@ På et tidspunkt vil `mapping`-egenskapen bli fjernet, men når det skjer vil ve Man kan legge til dynamiske parametre ved å sette opp `mapping` på den aktuelle komponenten: -```json +```json {hl_lines=["12-14"]} { "id": "dropdown-komponent", "type": "Dropdown", @@ -218,7 +218,7 @@ Om man setter opp en kobling til et datafelt og dette feltet endrer seg, så vil Å sende med parametre fra repeterende grupper gjøres ved å legge ved en indeks-indikator for de relevante gruppene. Eksempel: -```json +```json {hl_lines=[13]} { "id": "dropdown-group", "type": "Dropdown", @@ -238,7 +238,7 @@ Om man setter opp en kobling til et datafelt og dette feltet endrer seg, så vil For nøstede repeterende grupper vil man følge det samme mønsteret, men med en ekstra indikator for den nøstede gruppa: -```json +```json {hl_lines=[13]} { "id": "dropdown-nested-group", "type": "Dropdown", From 81141b92944aabfbaeb62721397a00802806ad68 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 09:44:43 +0100 Subject: [PATCH 07/31] Adding links to the options guide instead of individual components in expression docs --- .../reference/logic/expressions/_index.en.md | 33 ++++++++++--------- .../reference/logic/expressions/_index.nb.md | 33 ++++++++++--------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/content/altinn-studio/reference/logic/expressions/_index.en.md b/content/altinn-studio/reference/logic/expressions/_index.en.md index 786daa7481..98338381b2 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.en.md +++ b/content/altinn-studio/reference/logic/expressions/_index.en.md @@ -146,22 +146,23 @@ And for a person who is 15 years old (or younger, such as a 4-year-old), the tex Dynamic expressions are currently available for use in these properties, as defined in [layout files](../../ux/pages). -| Components | Property | Expected Value | Frontend | Backend | -| -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | -------------------------- | -------- | ------- | -| [Pages/layouts](#showhide-entire-pages) | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | -| All | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | -| Form components | `required` | [Boolean](#boolean-values) | ✅ | ✅ | -| Form components | `readOnly` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [RadioButtons](../../ux/components/radiobuttons), [Checkboxes](../../ux/components/checkbox), [Dropdown](../../ux/components/dropdown) | `source.label` | [String](#strings) | ✅ | ❌ | -| [RadioButtons](../../ux/components/radiobuttons), [Checkboxes](../../ux/components/checkbox), [Dropdown](../../ux/components/dropdown) | `source.description` | [String](#strings) | ✅ | ❌ | -| [RadioButtons](../../ux/components/radiobuttons), [Checkboxes](../../ux/components/checkbox), [Dropdown](../../ux/components/dropdown) | `source.helpText` | [String](#strings) | ✅ | ❌ | -| All | `textResourceBindings.[*]` \* | [String](#strings) | ✅ | ❌ | +| Components | Property | Expected Value | Frontend | Backend | +|--------------------------------------------------------------------------------------------------------|-------------------------------|----------------------------|----------|---------| +| [Pages/layouts](#showhide-entire-pages) | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | +| All | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | +| Form components | `required` | [Boolean](#boolean-values) | ✅ | ✅ | +| Form components | `readOnly` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/static-codelists) | `source.label` | [String](#strings) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/static-codelists) | `source.description` | [String](#strings) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/static-codelists) | `source.helpText` | [String](#strings) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/dynamic-codelists/#based-on-expressions) | `queryParameters.[*]` | [String](#strings) | ✅ | ❌ | +| All | `textResourceBindings.[*]` \* | [String](#strings) | ✅ | ❌ | \* = The values that can be overridden with textResourceBindings vary from component to component, but will work wherever used. For repeating groups, you can find [more information here](../../ux/fields/grouping/repeating#textresourcebindings) diff --git a/content/altinn-studio/reference/logic/expressions/_index.nb.md b/content/altinn-studio/reference/logic/expressions/_index.nb.md index 58442a76a6..94e0d687c1 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.nb.md +++ b/content/altinn-studio/reference/logic/expressions/_index.nb.md @@ -141,22 +141,23 @@ Og for en person som er 15 år (eller yngre, som f.eks. en 4-åring), returneres Dynamiske uttrykk er foreløpig tilgjengelig for bruk i disse egenskapene, som definert i [layout-filer](../../ux/pages). -| Komponenter | Egenskap | Forventet verdi | Frontend | Backend | -| --------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | -------------------------- | -------- | ------- | -| [Sider/layouts](#viseskjule-hele-sider) | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| Alle | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| Skjemakomponenter | `required` | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| Skjemakomponenter | `readOnly` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Radioknapper](../../ux/components/radiobuttons), [Avkrysningsbokser](../../ux/components/checkbox), [Nedtrekksliste](../../ux/components/dropdown) | `source.label` | [Streng](#strenger) | ✅ | ❌ | -| [Radioknapper](../../ux/components/radiobuttons), [Avkrysningsbokser](../../ux/components/checkbox), [Nedtrekksliste](../../ux/components/dropdown) | `source.description` | [Streng](#strenger) | ✅ | ❌ | -| [Radioknapper](../../ux/components/radiobuttons), [Avkrysningsbokser](../../ux/components/checkbox), [Nedtrekksliste](../../ux/components/dropdown) | `source.helpText` | [Streng](#strenger) | ✅ | ❌ | -| Alle | `textResourceBindings.[*]` \* | [Streng](#strenger) | ✅ | ❌ | +| Komponenter | Egenskap | Forventet verdi | Frontend | Backend | +|----------------------------------------------------------------------------------------------------------|-------------------------------|----------------------------|----------|---------| +| [Sider/layouts](#viseskjule-hele-sider) | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| Alle | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| Skjemakomponenter | `required` | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| Skjemakomponenter | `readOnly` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/static-codelists) | `source.label` | [Streng](#strenger) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/static-codelists) | `source.description` | [Streng](#strenger) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/static-codelists) | `source.helpText` | [Streng](#strenger) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/dynamic-codelists/#basert-på-uttrykk) | `queryParameters.[*]` | [Streng](#strenger) | ✅ | ❌ | +| Alle | `textResourceBindings.[*]` \* | [Streng](#strenger) | ✅ | ❌ | \* = Hvilke verdier man kan overstyre med textResourceBindings varierer fra komponent til komponent, men vil fungere på alle steder der det brukes. TextResourceBindings for repeterende grupper finner From 82ecfad5f63b28e50df9ffb41ca4373f81b75327 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 09:47:22 +0100 Subject: [PATCH 08/31] Fixing broken link markdown --- .../guides/development/options/common-codelists/_index.nb.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md index 59e550a02f..3f02910d17 100644 --- a/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md @@ -39,7 +39,7 @@ Denne funksjonaliteten krever at applikasjonen benytter minimum [versjon 7.8.0]( Ved å kalle denne metoden vil du registrere alle kodelistene på tvers av alle kilder. Du kan også registrere kodelistene én og én hvis du vil ha kontroll på hvilke kodelister som er tatt i bruk eller konfigurere og tilpasse oppsettet av kodelisten. ### 3. Koble applikasjonen din til kodeverket du ønsker å bruke - Se (dokuemntasjon)[https://github.com/Altinn/codelists-lib-dotnet#available-codelists] nedenfor for tilgjengelige kodelister. + Se [dokuemntasjon](https://github.com/Altinn/codelists-lib-dotnet#available-codelists) nedenfor for tilgjengelige kodelister. Du kan gjøre dette enten ved hjelp av [Altinn Studio](https://altinn.studio) og konfigurere *Kodeliste-ID* for komponenten din i brukergrensesnittet. From 2760e512c3b3d9ad8b35071203ec98c91e9510b4 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 09:50:20 +0100 Subject: [PATCH 09/31] Removing minimum version info (this version is getting old now) --- .../guides/development/options/common-codelists/_index.en.md | 4 ---- .../guides/development/options/common-codelists/_index.nb.md | 4 ---- 2 files changed, 8 deletions(-) diff --git a/content/altinn-studio/guides/development/options/common-codelists/_index.en.md b/content/altinn-studio/guides/development/options/common-codelists/_index.en.md index abfc8352c6..87d22ad891 100644 --- a/content/altinn-studio/guides/development/options/common-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/common-codelists/_index.en.md @@ -6,10 +6,6 @@ toc: false weight: 200 --- -{{%notice info%}} -This functionality requires that the application uses at least [version 7.8.0](https://github.com/Altinn/app-lib-dotnet/releases/tag/v7.8.0) of the Altinn.App.Core NuGet package. -{{% /notice%}} - ## What are common standard code lists? Common standard code lists are lists such as countries, counties, municipalities, genders, marital statuses, etc. that can be used in an application without the need to maintain these code lists yourself. See the [complete list](https://github.com/Altinn/codelists-lib-dotnet#available-codelists) of available code lists. diff --git a/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md index 3f02910d17..00404c158d 100644 --- a/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md @@ -6,10 +6,6 @@ toc: false weight: 200 --- -{{%notice info%}} -Denne funksjonaliteten krever at applikasjonen benytter minimum [versjon 7.8.0](https://github.com/Altinn/app-lib-dotnet/releases/tag/v7.8.0) av Altinn.App.Core nuget pakken. -{{% /notice%}} - ## Hva er felles standard kodelister? Felles standard kodelister er lister som land, fylker, kommuner, kjønn, sivilstatus etc som man kan benytte i sin applikasjon uten at man selv trenger å vedlikeholde disse kodelistene selv. Se [komplett liste](https://github.com/Altinn/codelists-lib-dotnet#available-codelists) over tilgjengelige kodelister. From 0816b4917a7306b87ad0491149a40e9bca6983d9 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 12:16:48 +0100 Subject: [PATCH 10/31] Making new sections for functionality, moving sections about sources --- .../altinn-studio/guides/development/options/_index.en.md | 4 ++-- .../altinn-studio/guides/development/options/_index.nb.md | 4 ++-- .../guides/development/options/functionality/_index.en.md | 7 +++++++ .../guides/development/options/functionality/_index.nb.md | 7 +++++++ .../options/functionality/automatic-cleanup/_index.en.md | 4 ++++ .../options/functionality/automatic-cleanup/_index.nb.md | 4 ++++ .../options/functionality/data-binding/_index.en.md | 4 ++++ .../options/functionality/data-binding/_index.nb.md | 4 ++++ .../options/functionality/filtering/_index.en.md | 4 ++++ .../options/functionality/filtering/_index.nb.md | 4 ++++ .../options/functionality/preselection/_index.en.md | 4 ++++ .../options/functionality/preselection/_index.nb.md | 4 ++++ .../development/options/functionality/sorting/_index.en.md | 4 ++++ .../development/options/functionality/sorting/_index.nb.md | 4 ++++ .../guides/development/options/sources/_index.en.md | 7 +++++++ .../guides/development/options/sources/_index.nb.md | 7 +++++++ .../{altinn2-codelists => sources/altinn2}/_index.en.md | 2 ++ .../{altinn2-codelists => sources/altinn2}/_index.nb.md | 2 ++ .../{dynamic-codelists => sources/dynamic}/_index.en.md | 2 ++ .../{dynamic-codelists => sources/dynamic}/_index.nb.md | 2 ++ .../from-data-model}/_index.en.md | 2 ++ .../from-data-model}/_index.nb.md | 2 ++ .../{common-codelists => sources/shared}/_index.en.md | 2 ++ .../{common-codelists => sources/shared}/_index.nb.md | 2 ++ .../{static-codelists => sources/static}/_index.en.md | 5 ++++- .../{static-codelists => sources/static}/_index.nb.md | 3 +++ 26 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 content/altinn-studio/guides/development/options/functionality/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/functionality/_index.nb.md create mode 100644 content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md create mode 100644 content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md create mode 100644 content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md create mode 100644 content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md create mode 100644 content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md create mode 100644 content/altinn-studio/guides/development/options/sources/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/sources/_index.nb.md rename content/altinn-studio/guides/development/options/{altinn2-codelists => sources/altinn2}/_index.en.md (97%) rename content/altinn-studio/guides/development/options/{altinn2-codelists => sources/altinn2}/_index.nb.md (97%) rename content/altinn-studio/guides/development/options/{dynamic-codelists => sources/dynamic}/_index.en.md (99%) rename content/altinn-studio/guides/development/options/{dynamic-codelists => sources/dynamic}/_index.nb.md (99%) rename content/altinn-studio/guides/development/options/{repeating-group-codelists => sources/from-data-model}/_index.en.md (97%) rename content/altinn-studio/guides/development/options/{repeating-group-codelists => sources/from-data-model}/_index.nb.md (96%) rename content/altinn-studio/guides/development/options/{common-codelists => sources/shared}/_index.en.md (98%) rename content/altinn-studio/guides/development/options/{common-codelists => sources/shared}/_index.nb.md (98%) rename content/altinn-studio/guides/development/options/{static-codelists => sources/static}/_index.en.md (93%) rename content/altinn-studio/guides/development/options/{static-codelists => sources/static}/_index.nb.md (94%) diff --git a/content/altinn-studio/guides/development/options/_index.en.md b/content/altinn-studio/guides/development/options/_index.en.md index da5fd198a4..c475a28920 100644 --- a/content/altinn-studio/guides/development/options/_index.en.md +++ b/content/altinn-studio/guides/development/options/_index.en.md @@ -1,6 +1,6 @@ --- -title: Code lists (options) -linktitle: Code lists +title: Options (code lists) +linktitle: Options description: How to configure Options / Code lists for an app? toc: true weight: 40 diff --git a/content/altinn-studio/guides/development/options/_index.nb.md b/content/altinn-studio/guides/development/options/_index.nb.md index 19d6c567ee..96bc1d1184 100644 --- a/content/altinn-studio/guides/development/options/_index.nb.md +++ b/content/altinn-studio/guides/development/options/_index.nb.md @@ -1,6 +1,6 @@ --- -title: Kodelister (svaralternativer) -linktitle: Kodelister +title: Svaralternativer (kodelister) +linktitle: Svaralternativer description: Hvordan konfigurere svaralternativer/kodelister for en app? toc: true weight: 40 diff --git a/content/altinn-studio/guides/development/options/functionality/_index.en.md b/content/altinn-studio/guides/development/options/functionality/_index.en.md new file mode 100644 index 0000000000..970f7b9edc --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/_index.en.md @@ -0,0 +1,7 @@ +--- +title: Functionality +description: Common functionality for all option sources +weight: 20 +--- + +{{}} diff --git a/content/altinn-studio/guides/development/options/functionality/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/_index.nb.md new file mode 100644 index 0000000000..51e195d667 --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/_index.nb.md @@ -0,0 +1,7 @@ +--- +title: Funksjonalitet +description: Felles funksjonalitet for alle kildene til kodelister +weight: 20 +--- + +{{}} diff --git a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md new file mode 100644 index 0000000000..6813eefb6e --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md @@ -0,0 +1,4 @@ +--- +title: Automatic cleanup +description: How unknown options are automatically removed from the data model +--- diff --git a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md new file mode 100644 index 0000000000..fe0658e1b8 --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md @@ -0,0 +1,4 @@ +--- +title: Automatisk opprydding +description: Hvordan ukjente svaralternativer automatisk fjernes fra datamodellen +--- diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md new file mode 100644 index 0000000000..58c8fe5a7f --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md @@ -0,0 +1,4 @@ +--- +title: Data binding +description: What can be stored in the data model +--- diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md new file mode 100644 index 0000000000..fb155d699d --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md @@ -0,0 +1,4 @@ +--- +title: Dataknytning +description: Hva kan lagres i datamodellen +--- diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md new file mode 100644 index 0000000000..ab62490a78 --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md @@ -0,0 +1,4 @@ +--- +title: Filtering +description: Removing some options from the list +--- diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md new file mode 100644 index 0000000000..33d4005333 --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md @@ -0,0 +1,4 @@ +--- +title: Filtrering +description: Fjerne noen alternativer fra listen +--- diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md new file mode 100644 index 0000000000..7f4c2f421d --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md @@ -0,0 +1,4 @@ +--- +title: Pre-selection +description: Making one option selected by default +--- diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md new file mode 100644 index 0000000000..783ffc0027 --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md @@ -0,0 +1,4 @@ +--- +title: Forhåndsvalg +description: Gjør et av alternativene forhåndsvalgt +--- diff --git a/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md b/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md new file mode 100644 index 0000000000..dd46afb040 --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md @@ -0,0 +1,4 @@ +--- +title: Sorting +description: Sorting the options in the list +--- diff --git a/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md new file mode 100644 index 0000000000..f2f5749c4e --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md @@ -0,0 +1,4 @@ +--- +title: Sortering +description: Sortere valgene i listen +--- diff --git a/content/altinn-studio/guides/development/options/sources/_index.en.md b/content/altinn-studio/guides/development/options/sources/_index.en.md new file mode 100644 index 0000000000..f351d77c06 --- /dev/null +++ b/content/altinn-studio/guides/development/options/sources/_index.en.md @@ -0,0 +1,7 @@ +--- +title: Sources +description: The different sources for code lists in Altinn Studio +weight: 10 +--- + +{{}} diff --git a/content/altinn-studio/guides/development/options/sources/_index.nb.md b/content/altinn-studio/guides/development/options/sources/_index.nb.md new file mode 100644 index 0000000000..bf3efc6c63 --- /dev/null +++ b/content/altinn-studio/guides/development/options/sources/_index.nb.md @@ -0,0 +1,7 @@ +--- +title: Kilder +description: De ulike kildene Alting Studio kan bruke for kodelister +weight: 10 +--- + +{{}} diff --git a/content/altinn-studio/guides/development/options/altinn2-codelists/_index.en.md b/content/altinn-studio/guides/development/options/sources/altinn2/_index.en.md similarity index 97% rename from content/altinn-studio/guides/development/options/altinn2-codelists/_index.en.md rename to content/altinn-studio/guides/development/options/sources/altinn2/_index.en.md index 5996648078..24a9c6f1a4 100644 --- a/content/altinn-studio/guides/development/options/altinn2-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/altinn2/_index.en.md @@ -4,6 +4,8 @@ linktitle: Code lists from Altinn 2 description: How to configure code lists that exists in Altinn 2 in an Altinn 3 app? toc: false weight: 300 +aliases: + - /altinn-studio/guides/development/options/altinn2-codelists --- {{}} **Deprecated feature** diff --git a/content/altinn-studio/guides/development/options/altinn2-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/sources/altinn2/_index.nb.md similarity index 97% rename from content/altinn-studio/guides/development/options/altinn2-codelists/_index.nb.md rename to content/altinn-studio/guides/development/options/sources/altinn2/_index.nb.md index dbd4557d6c..6280d10fb6 100644 --- a/content/altinn-studio/guides/development/options/altinn2-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/altinn2/_index.nb.md @@ -4,6 +4,8 @@ linktitle: Kodelister fra Altinn 2 description: Hvordan konfigurere kodelister fra Altinn 2 i en Altinn 3 applikasjon? toc: false weight: 300 +aliases: + - /nb/altinn-studio/guides/development/options/altinn2-codelists --- {{}} **Utgående funksjonalitet** diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md similarity index 99% rename from content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md rename to content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md index 150277fccd..a80ace3756 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md @@ -3,6 +3,8 @@ title: Dynamic code lists generated runtime linktitle: Dynamic code lists toc: false weight: 100 +aliases: + - /altinn-studio/guides/development/options/dynamic-codelists --- In an Altinn 3 app you can also have dynamic code lists that are generated runtime. This makes it possible to have dynamic lists that are filtered or looked up in external sources. Dynamic code lists can either be public (accessible to all, without authentication), or secured and limited to those with read access to the instance. diff --git a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md similarity index 99% rename from content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md rename to content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md index 1238a6bf2c..c407009dbb 100644 --- a/content/altinn-studio/guides/development/options/dynamic-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md @@ -3,6 +3,8 @@ title: Dynamiske kodelister generert under kjøring av applikasjonen linktitle: Dynamiske kodelister toc: false weight: 100 +aliases: + - /nb/altinn-studio/guides/development/options/dynamic-codelists --- I en Altinn 3 app har man også mulighet til å ha dynamisk kodelister som produseres dynamisk ved kjøring av appen. Dette gjør det mulig å lage dynamiske verdier, for eksempel ved å hente og filtrere verdier fra andre kilder. Dynamiske kodelister kan enten være åpne (tilgjengelig for alle, uten autentisering), eller sikret slik at brukeren må ha tilgang til instansen for å hente kodelisten. diff --git a/content/altinn-studio/guides/development/options/repeating-group-codelists/_index.en.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md similarity index 97% rename from content/altinn-studio/guides/development/options/repeating-group-codelists/_index.en.md rename to content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md index 82d2790239..69fbd5c143 100644 --- a/content/altinn-studio/guides/development/options/repeating-group-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md @@ -3,6 +3,8 @@ title: Code lists based on repeating groups from the data model linktitle: From repeating groups description: How to configure code lists that gets it's values from a repeating group from the datamodel? weight: 150 +aliases: + - /altinn-studio/guides/development/options/repeating-group-codelists --- Traditional options are based on resources fetched from the backend. diff --git a/content/altinn-studio/guides/development/options/repeating-group-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md similarity index 96% rename from content/altinn-studio/guides/development/options/repeating-group-codelists/_index.nb.md rename to content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md index 2b9e7de942..b978ab30ed 100644 --- a/content/altinn-studio/guides/development/options/repeating-group-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md @@ -3,6 +3,8 @@ title: Kodelister fra repeterede grupper i datamodellen linktitle: Fra repeterende grupper description: Hvordan konfigurere kodelister som får verdiene sine basert på verdier hentet fra en repeterende gruppe i datamodellen? weight: 150 +aliases: + - /nb/altinn-studio/guides/development/options/repeating-group-codelists --- Tradisjonelle options baserer seg på ressurser hentet fra backend. diff --git a/content/altinn-studio/guides/development/options/common-codelists/_index.en.md b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md similarity index 98% rename from content/altinn-studio/guides/development/options/common-codelists/_index.en.md rename to content/altinn-studio/guides/development/options/sources/shared/_index.en.md index 87d22ad891..89ed00618a 100644 --- a/content/altinn-studio/guides/development/options/common-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md @@ -4,6 +4,8 @@ linktitle: Common shared code list description: How to re-use common code lists shared across applications? toc: false weight: 200 +aliases: + - /altinn-studio/guides/development/options/common-codelists --- ## What are common standard code lists? diff --git a/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md similarity index 98% rename from content/altinn-studio/guides/development/options/common-codelists/_index.nb.md rename to content/altinn-studio/guides/development/options/sources/shared/_index.nb.md index 00404c158d..dfd51daa88 100644 --- a/content/altinn-studio/guides/development/options/common-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md @@ -4,6 +4,8 @@ linktitle: Felles standard kodelister description: Hvordan bruke felles standard kodelister på tvers av applikasjoner i Altinn 3? toc: false weight: 200 +aliases: + - /nb/altinn-studio/guides/development/options/common-codelists --- ## Hva er felles standard kodelister? diff --git a/content/altinn-studio/guides/development/options/static-codelists/_index.en.md b/content/altinn-studio/guides/development/options/sources/static/_index.en.md similarity index 93% rename from content/altinn-studio/guides/development/options/static-codelists/_index.en.md rename to content/altinn-studio/guides/development/options/sources/static/_index.en.md index 9c5f7362cc..38e8704804 100644 --- a/content/altinn-studio/guides/development/options/static-codelists/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.en.md @@ -1,7 +1,10 @@ --- -title: Static code lists +title: Static options +description: Lists of options that does not change, but can be filtered toc: false weight: 50 +aliases: + - /altinn-studio/guides/development/options/static-codelists --- For simpler use-cases, a static code list is easy to configure. These can either be set directly in the component diff --git a/content/altinn-studio/guides/development/options/static-codelists/_index.nb.md b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md similarity index 94% rename from content/altinn-studio/guides/development/options/static-codelists/_index.nb.md rename to content/altinn-studio/guides/development/options/sources/static/_index.nb.md index ab4d446ffb..a28fe9fece 100644 --- a/content/altinn-studio/guides/development/options/static-codelists/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md @@ -1,7 +1,10 @@ --- title: Statiske kodelister +description: Kodelister som ikke endrer seg, men som kan filtreres toc: false weight: 50 +aliases: + - /nb/altinn-studio/guides/development/options/static-codelists --- For enklere brukstilfeller er statiske kodelister det letteste å sette opp. Disse kan enten settes direkte From 1cd478cec1f36f3a57a63fb290759492b6da3cc5 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 12:43:23 +0100 Subject: [PATCH 11/31] Improving titles and descriptions, adding an intro table for sources --- .../guides/development/options/sources/_index.en.md | 13 ++++++++++++- .../guides/development/options/sources/_index.nb.md | 12 +++++++++++- .../options/sources/altinn2/_index.en.md | 6 +++--- .../options/sources/altinn2/_index.nb.md | 6 +++--- .../options/sources/dynamic/_index.en.md | 5 +++-- .../options/sources/dynamic/_index.nb.md | 5 +++-- .../options/sources/from-data-model/_index.en.md | 4 ++-- .../options/sources/from-data-model/_index.nb.md | 6 +++--- .../development/options/sources/shared/_index.en.md | 6 +++--- .../development/options/sources/shared/_index.nb.md | 6 +++--- .../development/options/sources/static/_index.en.md | 5 +++-- .../development/options/sources/static/_index.nb.md | 9 +++++---- 12 files changed, 54 insertions(+), 29 deletions(-) diff --git a/content/altinn-studio/guides/development/options/sources/_index.en.md b/content/altinn-studio/guides/development/options/sources/_index.en.md index f351d77c06..8b8b8349fc 100644 --- a/content/altinn-studio/guides/development/options/sources/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/_index.en.md @@ -1,7 +1,18 @@ --- title: Sources -description: The different sources for code lists in Altinn Studio +description: The different sources for options in Altinn Studio weight: 10 --- +When you set up an options-enabled component in Altinn Studio, it needs to be connected to a source of options. There are three different properties in the component configuration that can be used for this, depending on the use case: + + +| Property | Usage | +|-------------|-----------------------------------------------------------------------------------------------------------------------------------| +| `options` | [Static options defined per-component](./static/#in-component-configuration) | +| `optionsId` | Either [static options from on json files](./static/#from-json-files), [dynamic options](./dynamic) or [shared options](./shared) | +| `source` | [Options from the data model](./from-data-model) | + +At least one such property has to be set in the component configuration. If multiple are set, the configuration precedence will be the opposite of the table above, so `source` will take precedence over `optionsId`, which will take precedence over `options`. + {{}} diff --git a/content/altinn-studio/guides/development/options/sources/_index.nb.md b/content/altinn-studio/guides/development/options/sources/_index.nb.md index bf3efc6c63..92476c98f8 100644 --- a/content/altinn-studio/guides/development/options/sources/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/_index.nb.md @@ -1,7 +1,17 @@ --- title: Kilder -description: De ulike kildene Alting Studio kan bruke for kodelister +description: De ulike kildene Altinn Studio kan bruke for svaralternativer weight: 10 --- +Når du setter opp en komponent i Altinn Studio som skal ha svaralternativer, må den kobles til en kilde for svaralternativer. Det er tre forskjellige egenskaper i komponentkonfigurasjonen som kan brukes til dette, avhengig av bruksområdet: + +| Egenskap | Bruksområde | +|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `options` | [Statiske svaralternativer definert per komponent](./static/#i-komponentkonfigurasjonen) | +| `optionsId` | Enten [statiske svaralternativer fra json-filer](./static/#fra-json-filer), [dynamiske svaralternativer](./dynamic) eller [delte svaralternativer](./shared) | +| `source` | [Svaralternativer fra datamodellen](./from-data-model) | + +Minst en slik egenskap må settes i komponentkonfigurasjonen. Hvis flere er satt, vil konfigurasjonsprioriteten være motsatt av tabellen ovenfor, slik at `source` vil ha forrang over `optionsId`, som vil ha forrang over `options`. + {{}} diff --git a/content/altinn-studio/guides/development/options/sources/altinn2/_index.en.md b/content/altinn-studio/guides/development/options/sources/altinn2/_index.en.md index 24a9c6f1a4..cf8f107e3d 100644 --- a/content/altinn-studio/guides/development/options/sources/altinn2/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/altinn2/_index.en.md @@ -1,7 +1,7 @@ --- -title: Re-use code lists from Altinn 2 -linktitle: Code lists from Altinn 2 -description: How to configure code lists that exists in Altinn 2 in an Altinn 3 app? +title: Re-use options from Altinn 2 +linktitle: From Altinn 2 +description: Options fetched from Altinn 2 toc: false weight: 300 aliases: diff --git a/content/altinn-studio/guides/development/options/sources/altinn2/_index.nb.md b/content/altinn-studio/guides/development/options/sources/altinn2/_index.nb.md index 6280d10fb6..b3d75d10a3 100644 --- a/content/altinn-studio/guides/development/options/sources/altinn2/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/altinn2/_index.nb.md @@ -1,7 +1,7 @@ --- -title: Gjenbruk av kodelister fra Altinn 2 -linktitle: Kodelister fra Altinn 2 -description: Hvordan konfigurere kodelister fra Altinn 2 i en Altinn 3 applikasjon? +title: Gjenbruk av svaralternativer fra Altinn 2 +linktitle: Fra Altinn 2 +description: Svaralternativer hentet fra Altinn 2 toc: false weight: 300 aliases: diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md index a80ace3756..7e81082ac4 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md @@ -1,6 +1,7 @@ --- -title: Dynamic code lists generated runtime -linktitle: Dynamic code lists +title: Dynamic options +linktitle: Dynamic +description: Generated runtime by custom C# code toc: false weight: 100 aliases: diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md index c407009dbb..34f6d30dc4 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md @@ -1,6 +1,7 @@ --- -title: Dynamiske kodelister generert under kjøring av applikasjonen -linktitle: Dynamiske kodelister +title: Dynamiske svaralternativer +linktitle: Dynamisk +description: Generert ved kjøring fra C#-kode toc: false weight: 100 aliases: diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md index 69fbd5c143..71eb43c1cb 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md @@ -1,7 +1,7 @@ --- title: Code lists based on repeating groups from the data model -linktitle: From repeating groups -description: How to configure code lists that gets it's values from a repeating group from the datamodel? +linktitle: From data model +description: Options made from a repeating structure in the data model weight: 150 aliases: - /altinn-studio/guides/development/options/repeating-group-codelists diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md index b978ab30ed..a9a3554ec1 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md @@ -1,7 +1,7 @@ --- -title: Kodelister fra repeterede grupper i datamodellen -linktitle: Fra repeterende grupper -description: Hvordan konfigurere kodelister som får verdiene sine basert på verdier hentet fra en repeterende gruppe i datamodellen? +title: Svaralternativer fra repeterede strukturer +linktitle: Fra datamodellen +description: Svaralternativer hentet fra en repeterende struktur i datamodellen weight: 150 aliases: - /nb/altinn-studio/guides/development/options/repeating-group-codelists diff --git a/content/altinn-studio/guides/development/options/sources/shared/_index.en.md b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md index 89ed00618a..d3caa4b80e 100644 --- a/content/altinn-studio/guides/development/options/sources/shared/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md @@ -1,7 +1,7 @@ --- -title: Common shared code lists -linktitle: Common shared code list -description: How to re-use common code lists shared across applications? +title: Common shared options +linktitle: Shared +description: Options that are shared across applications toc: false weight: 200 aliases: diff --git a/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md index dfd51daa88..dca88b30c2 100644 --- a/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md @@ -1,7 +1,7 @@ --- -title: Felles standard kodelister -linktitle: Felles standard kodelister -description: Hvordan bruke felles standard kodelister på tvers av applikasjoner i Altinn 3? +title: Delte standard kodelister +linktitle: Delte +description: Delte standard kodelister som kan brukes i flere applikasjoner toc: false weight: 200 aliases: diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.en.md b/content/altinn-studio/guides/development/options/sources/static/_index.en.md index 38e8704804..34c6ccadb0 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.en.md @@ -1,5 +1,6 @@ --- title: Static options +linktitle: Static description: Lists of options that does not change, but can be filtered toc: false weight: 50 @@ -11,7 +12,7 @@ For simpler use-cases, a static code list is easy to configure. These can either configuration or in a json file in the application repository. Which method to use depends on the re-usability of the code list. If multiple components should use the same code list, it is recommended to use the json file method. -## Static code lists based on component configuration +## In component configuration In the example configuration, a Dropdown component is set up with a static code list. The `options` property is an array of objects, where each object represents a code list item. The `value` property is the value that will be @@ -43,7 +44,7 @@ the user. } ``` -## Static code lists based on json files +## From JSON files By adding json based option files in the application repository, the application will automatically read the file and expose it through the options api. For this to work, the files must be placed in the `App/options/` folder and be named according to the following conventions `{optionId}.json` for the application to recognize them. diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md index a28fe9fece..b4ef3e8665 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md @@ -1,6 +1,7 @@ --- -title: Statiske kodelister -description: Kodelister som ikke endrer seg, men som kan filtreres +title: Statiske svaralternativer +linktitle: Statisk +description: Svaralternativer som ikke endrer seg, men som kan filtreres toc: false weight: 50 aliases: @@ -12,7 +13,7 @@ i komponentkonfigurasjonen eller i en json-fil i app-repositoriet. Hvilken metod gjenbruksbehovet til kodelisten. Hvis flere komponenter skal bruke samme kodeliste, anbefales det å bruke metoden med json-filen. -## Statiske kodelister basert på komponentkonfigurasjon +## I komponentkonfigurasjonen I denne eksempelkonfigurasjonen er en Dropdown-komponent satt opp med en statisk kodeliste. Egenskapen `options` er en array av objekter, hvor hvert objekt representerer et kodelisteelement. Egenskapen `value` er verdien som vil bli @@ -43,7 +44,7 @@ lagret i datamodellen når brukeren velger elementet. Egenskapen `label` er teks } ``` -## Statiske kodelister basert på json-filer +## Fra JSON-filer Ved å legge json-lister i options mappen i app repo vil appen automatisk lese denne filen og eksponere det gjennom options-apiet. Options filene må ligge under `App/options/` og vil bli differensiert ved hjelp av navngivningen på json-filen. F.eks `land.json`. Her vil da optionsId være `land`, og vil være eksponert gjennom endepunktet `{org}/{app}/api/options/land`. From 39b22dc14d52e6ce04560f5008abf6616e6517d1 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 13:05:31 +0100 Subject: [PATCH 12/31] Moving some stuff out, and making the top-most page introductory --- .../guides/development/options/_index.en.md | 137 ++--------------- .../guides/development/options/_index.nb.md | 138 ++---------------- .../functionality/data-binding/_index.en.md | 44 ++++++ .../functionality/data-binding/_index.nb.md | 44 ++++++ .../options/functionality/texts/_index.en.md | 68 +++++++++ .../options/functionality/texts/_index.nb.md | 68 +++++++++ 6 files changed, 250 insertions(+), 249 deletions(-) create mode 100644 content/altinn-studio/guides/development/options/functionality/texts/_index.en.md create mode 100644 content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md diff --git a/content/altinn-studio/guides/development/options/_index.en.md b/content/altinn-studio/guides/development/options/_index.en.md index c475a28920..ef782fb754 100644 --- a/content/altinn-studio/guides/development/options/_index.en.md +++ b/content/altinn-studio/guides/development/options/_index.en.md @@ -9,133 +9,20 @@ aliases: - /altinn-studio/reference/data/options --- -Altinn offers two different ways an application can use code lists - static and dynamic. Both is primarily exposed -through the options api from application, and are available at `{org}/{app}/api/options/{optionsId}`. -Checkbox, Dropdown, and RadioButton components will automatically be able to fetch such lists if you connect the -component to the option id in question. Not all dynamic code list have to be fetched from the options api - we can also -have code lists based on the values from a repeating structure in the datamodel. +Several of the form components in Altinn 3 use options. The concept referred to as options is sometimes also called _code lists_. -## Connect the component to options (code list) +The following components support options: -This is done by adding the optionId you would like to refer to either through the component UI in Designer or directly -in `FormLayout.json` as shown below: +| Component | Type | Use case | +|-------------------------------------------------------------------------|-----------------------|----------------------------------------------------------------------------------------------------| +| [Dropdown](../../../reference/ux/components/dropdown) | Single choice | Used to select a single option from a dropdown list | +| [RadioButtons](../../../reference/ux/components/radiobuttons) | Single choice | Used to select a single option from a list of radio buttons | +| [List](../../../reference/ux/components/listcomponent) | Single choice | Used to select a single option from a list/table (with one radio button per row) | +| [Likert](../../../reference/ux/components/likert) | Single choice per row | Used to select a single option per row in a table, displayed as a scale. Commonly used in surveys. | +| [Checkboxes](../../../reference/ux/components/checkboxes) | Multiple choice | Used to select one or more options from a list of checkboxes | +| [MultipleSelect](../../../reference/ux/components/multipleselect) | Multiple choice | Used to select one or more options from a dropdown list | +| [FileUploadWithTag](../../../reference/ux/components/fileuploadwithtag) | Single choice | Used to upload a file and tag it with an option | -```json -{ - "id": "some-dropdown-component", - "type": "Dropdown", - "textResourceBindings": {}, - "dataModelBindings": {}, - "optionsId": "countries" -} -``` - -### Save label value in the datamodel -Sometimes you might wish to save the displayed value in the users chosen language to simplify creation of simple presentations of data without addtional lookups or a requirement to remember the label the user actually picked in case it have changed over time. - -This is performed by having a separate ``dataModelBindings`` with the key ``"label":`` in addition to ``"simpleBinding":`` - -```json -{ - "id": "dropdown-component", - "type": "Dropdown", - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype", - "label":"soknad.nyGaranti.loyvetypeLabel" - }, - "optionsId": "biler" -} -``` - -### Store metadata for the parameters used to retrieve options in tha datamodel - -You can store metadata for the parameters used to retrieve options in the datamodel by setting the `metadata` property -on the components `dataModelBinding` property: - -```json -{ - "id": "some-dropdown-component", - "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype", - "metadata": "soknad.transportorOrgnummer" - }, - "required": true, - "optionsId": "loyvetyper", - "mapping": { - "soknad.transportorOrgnummer": "orgnummer" - } -}, -``` - -This configuration will store the metadata of the retrieved options as a comma separated string in the -field `soknad.transportorOrgnummer` in the datamodel. - -## Description and HelpText - -`description` and `helpText` is supported by options in apps that use version v7.8.0 or higher. `description` and -`helpText` can be displayed by the components `RadioButtons` and `Checkboxes` by providing the option list with the -mentioned properties. - -Descriptions and HelpTexts can be provided to `options` in the same way that a `label` is provided, in either static or -dynamic code lists. One can also use them in options based on repeating groups in the `source` attribute. - -```json -[ - { - "value": "norway", - "label": "Norge", - "description": "This is a description", - "helpText": "This is a help text" - }, - { - "value": "denmark", - "label": "Danmark" - } -] -``` - -```cs -var options = new AppOptions -{ - Options = new List - { - new AppOption - { - Label = "Ole", - Value = "1", - Description = "This is a description", - HelpText = "This is a help text" - }, - new AppOption - { - Label = "Dole", - Value = "2" - } - } -}; -``` - -Descriptions and help texts used in options based on repeating groups can be set up with dynamic text-resources in the -same way as labels, described in -[options based on repeating groups](repeating-group-codelists). - -```json -{ - "id": "checkboxes-component-id", - "type": "Checkboxes", - ... - "source": { - "group": "some.group", - "label": "checkboxes.label", - "description": "checkboxes.descripiton", - "helpText": "checkboxes.helpText", - "value": "some.group[{0}].someField" - } -}, -``` +In the categories below, you can learn more about how to produce a list of options, configure that option list to be used in a component, as well as common functionality supported across these components. {{}} diff --git a/content/altinn-studio/guides/development/options/_index.nb.md b/content/altinn-studio/guides/development/options/_index.nb.md index 96bc1d1184..91ba0f4a32 100644 --- a/content/altinn-studio/guides/development/options/_index.nb.md +++ b/content/altinn-studio/guides/development/options/_index.nb.md @@ -1,7 +1,7 @@ --- -title: Svaralternativer (kodelister) +title: Svaralternativer linktitle: Svaralternativer -description: Hvordan konfigurere svaralternativer/kodelister for en app? +description: Hvordan konfigurere svaralternativer for en app toc: true weight: 40 aliases: @@ -9,130 +9,20 @@ aliases: - /nb/altinn-studio/reference/data/options --- -Altinn tilbyr to ulike måter en app kan eksponere kodelister på: Statisk og dynamisk. Disse eksponeres primært fra endepunktet som er tilgjengelig på `{org}/{app}/api/options/{optionsId}`, hvor `optionsId` er ID-en til listen. -Komponenter som avkrysningsbokser, radioknapper og nedtrekkslister vil automatisk kunne hente ut en slik liste om man kobler dem til en kodeliste-ID. Men ikke alle dynamiske kodelister må gå via API'et – vi har også dynamiske kodelister som baserer seg på verdiene fra en repeterende struktur i datamodellen. +Flere av skjemakomponentene i Altinn 3 bruker svaralternativer. Konseptet omtalt som svaralternativer kalles av og til også for _kodelister_ (eller _code lists_ og _options_ på engelsk). -## Koble en komponent til en kodeliste +Følgende komponenter støtter svaralternativer: -En komponent kobles til en kodeliste ved å legge til feltet `optionsId`, som refererer til kodelistens ID. Eksempel: +| Komponent | Type | Bruksområde | +|-------------------------------------------------------------------------|------------------|---------------------------------------------------------------------------------------------------------| +| [Dropdown](../../../reference/ux/components/dropdown) | Ett valg | Brukes for å velge ett alternativ fra en nedtrekksliste | +| [RadioButtons](../../../reference/ux/components/radiobuttons) | Ett valg | Brukes for å velge ett alternativ fra en liste med radioknapper | +| [List](../../../reference/ux/components/listcomponent) | Ett valg | Brukes for å velge ett alternativ fra en liste/tabell (med en radioknapp per rad) | +| [Likert](../../../reference/ux/components/likert) | Ett valg per rad | Brukes for å velge ett alternativ per rad i en tabell, vist som en skala. Vanlig i spørreundersøkelser. | +| [Checkboxes](../../../reference/ux/components/checkboxes) | Flere valg | Brukes for å velge ett eller flere alternativer fra en liste med avkrysningsbokser | +| [MultipleSelect](../../../reference/ux/components/multipleselect) | Flere valg | Brukes for å velge ett eller flere alternativer fra en nedtrekksliste | +| [FileUploadWithTag](../../../reference/ux/components/fileuploadwithtag) | Ett valg | Brukes for å laste opp en fil og knytte den til en 'tag'/merkelapp | -```json -{ - "id": "dropdown-komponent", - "type": "Dropdown", - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype" - }, - "optionsId": "biler" -} -``` - -### Lagre visningsverdi i datamodellen -Noen ganger ønsker man å lagre den viste verdien på brukerens språk i datamodellen for enklere å kunne bruke de lagrede dataene til å lagre enkle visninger uten å være avhengig av å gjøre et nytt oppslag for å få en visningsvennlig verdi. Det kan også brukes for å huske hva brukeren faktisk har sett når han valgte i tilfelle man endrer ordlyd for en verdi og vil ha logg for hva brukeren har sett. - -Dette gjøres ved å ha en egen ``dataModelBindings`` med navnet ``"label":`` i tillegg til en ``"simpleBinding":``. - -```json -{ - "id": "dropdown-komponent", - "type": "Dropdown", - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype", - "label":"soknad.nyGaranti.loyvetypeLabel" - }, - "optionsId": "biler" -} -``` - -### Lagre metadata for parametrene som ble brukt til å hente options - -Du kan lagre metadata for parameterene som ble brukt til å hente kodeliste i datamodellen ved å sette egenskapen `metadata` -på komponentens `dataModelBinding`-egenskap: - -```json -{ - "id": "some-dropdown-component", - "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, - "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype", - "metadata": "soknad.transportorOrgnummer" - }, - "required": true, - "optionsId": "loyvetyper", - "mapping": { - "soknad.transportorOrgnummer": "orgnummer" - } -} -``` - -Denne konfigurasjonen vil lagre metadata for parameterene som ble brukt til å hente kodelisten som en kommaseparert -streng i feltet `soknad.transportorOrgnummer` i datamodellen. - -## Beskrivelse og hjelpetekst - -`description` og `helpText` støttes av kodelister i apper som bruker versjon 7.8.0 eller høyere. Beskrivelse og -hjelpetekst kan vises av komponentene `RadioButtons` og `Checkboxes` ved å sette attributtene i en `option` som -brukes av komponenten. - -Beskrivelser og hjelpetekster kan gis til `options` på samme måte som en `label` er gitt, enten i statiske eller -dynamiske kodelister. Man kan også bruke dem i kodelister basert på repeterende grupper i `source`-attributten. - -```json -[ - { - "value": "norway", - "label": "Norge", - "description": "This is a description", - "helpText": "This is a help text" - }, - { - "value": "denmark", - "label": "Danmark" - } -] -``` - -```cs -var options = new AppOptions -{ - Options = new List - { - new AppOption - { - Label = "Ole", - Value = "1", - Description = "This is a description", - HelpText = "This is a help text" - }, - new AppOption - { - Label = "Dole", - Value = "2" - } - } -}; -``` - -Beskrivelser og hjelpetekster som brukes i kodelister basert på repeterende grupper kan settes opp med dynamiske -tekstressurser på samme måte som `label`, som beskrevet i -[kodelister fra repeterende grupper](repeating-group-codelists). - -```json -{ - "id": "checkboxes-component-id", - "type": "Checkboxes", - ... - "source": { - "group": "some.group", - "label": "checkboxes.label", - "description": "checkboxes.descripiton", - "helpText": "checkboxes.helpText", - "value": "some.group[{0}].someField" - } -} -``` +I kategoriene under kan du lære mer om hvordan du produserer en liste med svaralternativer, kobler den til en komponent, samt om felles funkjsonalitet som kan brukes på tvers av disse komponentene. {{}} diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md index 58c8fe5a7f..f24876ff5d 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md @@ -2,3 +2,47 @@ title: Data binding description: What can be stored in the data model --- + +### Save label value in the datamodel +Sometimes you might wish to save the displayed value in the users chosen language to simplify creation of simple presentations of data without addtional lookups or a requirement to remember the label the user actually picked in case it have changed over time. + +This is performed by having a separate ``dataModelBindings`` with the key ``"label":`` in addition to ``"simpleBinding":`` + +```json +{ + "id": "dropdown-component", + "type": "Dropdown", + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype", + "label":"soknad.nyGaranti.loyvetypeLabel" + }, + "optionsId": "biler" +} +``` + +### Store metadata for the parameters used to retrieve options in tha datamodel + +You can store metadata for the parameters used to retrieve options in the datamodel by setting the `metadata` property +on the components `dataModelBinding` property: + +```json +{ + "id": "some-dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "NyGarantiLoyvetype" + }, + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype", + "metadata": "soknad.transportorOrgnummer" + }, + "required": true, + "optionsId": "loyvetyper", + "mapping": { + "soknad.transportorOrgnummer": "orgnummer" + } +}, +``` + +This configuration will store the metadata of the retrieved options as a comma separated string in the +field `soknad.transportorOrgnummer` in the datamodel. diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md index fb155d699d..3983231966 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md @@ -2,3 +2,47 @@ title: Dataknytning description: Hva kan lagres i datamodellen --- + +### Lagre visningsverdi i datamodellen +Noen ganger ønsker man å lagre den viste verdien på brukerens språk i datamodellen for enklere å kunne bruke de lagrede dataene til å lagre enkle visninger uten å være avhengig av å gjøre et nytt oppslag for å få en visningsvennlig verdi. Det kan også brukes for å huske hva brukeren faktisk har sett når han valgte i tilfelle man endrer ordlyd for en verdi og vil ha logg for hva brukeren har sett. + +Dette gjøres ved å ha en egen ``dataModelBindings`` med navnet ``"label":`` i tillegg til en ``"simpleBinding":``. + +```json +{ + "id": "dropdown-komponent", + "type": "Dropdown", + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype", + "label":"soknad.nyGaranti.loyvetypeLabel" + }, + "optionsId": "biler" +} +``` + +### Lagre metadata for parametrene som ble brukt til å hente options + +Du kan lagre metadata for parameterene som ble brukt til å hente kodeliste i datamodellen ved å sette egenskapen `metadata` +på komponentens `dataModelBinding`-egenskap: + +```json +{ + "id": "some-dropdown-component", + "type": "Dropdown", + "textResourceBindings": { + "title": "NyGarantiLoyvetype" + }, + "dataModelBindings": { + "simpleBinding": "soknad.nyGaranti.loyvetype", + "metadata": "soknad.transportorOrgnummer" + }, + "required": true, + "optionsId": "loyvetyper", + "mapping": { + "soknad.transportorOrgnummer": "orgnummer" + } +} +``` + +Denne konfigurasjonen vil lagre metadata for parameterene som ble brukt til å hente kodelisten som en kommaseparert +streng i feltet `soknad.transportorOrgnummer` i datamodellen. \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md new file mode 100644 index 0000000000..3c9e686fa4 --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md @@ -0,0 +1,68 @@ +--- +title: Texts +description: The different text properties that can be used for options +--- + +## Description and HelpText + +`description` and `helpText` is supported by options in apps that use version v7.8.0 or higher. `description` and +`helpText` can be displayed by the components `RadioButtons` and `Checkboxes` by providing the option list with the +mentioned properties. + +Descriptions and HelpTexts can be provided to `options` in the same way that a `label` is provided, in either static or +dynamic code lists. One can also use them in options based on repeating groups in the `source` attribute. + +```json +[ + { + "value": "norway", + "label": "Norge", + "description": "This is a description", + "helpText": "This is a help text" + }, + { + "value": "denmark", + "label": "Danmark" + } +] +``` + +```cs +var options = new AppOptions +{ + Options = new List + { + new AppOption + { + Label = "Ole", + Value = "1", + Description = "This is a description", + HelpText = "This is a help text" + }, + new AppOption + { + Label = "Dole", + Value = "2" + } + } +}; +``` + +Descriptions and help texts used in options based on repeating groups can be set up with dynamic text-resources in the +same way as labels, described in +[options based on repeating groups](repeating-group-codelists). + +```json +{ + "id": "checkboxes-component-id", + "type": "Checkboxes", + ... + "source": { + "group": "some.group", + "label": "checkboxes.label", + "description": "checkboxes.descripiton", + "helpText": "checkboxes.helpText", + "value": "some.group[{0}].someField" + } +}, +``` \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md new file mode 100644 index 0000000000..ba0b69391b --- /dev/null +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md @@ -0,0 +1,68 @@ +--- +title: Tekster +description: De ulike tekstegenskapene som kan brukes for svaralternativer +--- + +## Beskrivelse og hjelpetekst + +`description` og `helpText` støttes av kodelister i apper som bruker versjon 7.8.0 eller høyere. Beskrivelse og +hjelpetekst kan vises av komponentene `RadioButtons` og `Checkboxes` ved å sette attributtene i en `option` som +brukes av komponenten. + +Beskrivelser og hjelpetekster kan gis til `options` på samme måte som en `label` er gitt, enten i statiske eller +dynamiske kodelister. Man kan også bruke dem i kodelister basert på repeterende grupper i `source`-attributten. + +```json +[ + { + "value": "norway", + "label": "Norge", + "description": "This is a description", + "helpText": "This is a help text" + }, + { + "value": "denmark", + "label": "Danmark" + } +] +``` + +```cs +var options = new AppOptions +{ + Options = new List + { + new AppOption + { + Label = "Ole", + Value = "1", + Description = "This is a description", + HelpText = "This is a help text" + }, + new AppOption + { + Label = "Dole", + Value = "2" + } + } +}; +``` + +Beskrivelser og hjelpetekster som brukes i kodelister basert på repeterende grupper kan settes opp med dynamiske +tekstressurser på samme måte som `label`, som beskrevet i +[kodelister fra repeterende grupper](repeating-group-codelists). + +```json +{ + "id": "checkboxes-component-id", + "type": "Checkboxes", + ... + "source": { + "group": "some.group", + "label": "checkboxes.label", + "description": "checkboxes.descripiton", + "helpText": "checkboxes.helpText", + "value": "some.group[{0}].someField" + } +} +``` \ No newline at end of file From 0e784574cced35d64d41e10f72fc4ab53a300d54 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 13:11:18 +0100 Subject: [PATCH 13/31] Clarifying that static isn't always static --- .../guides/development/options/sources/static/_index.en.md | 6 +++++- .../guides/development/options/sources/static/_index.nb.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.en.md b/content/altinn-studio/guides/development/options/sources/static/_index.en.md index 34c6ccadb0..d9ea6041d4 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.en.md @@ -10,7 +10,11 @@ aliases: For simpler use-cases, a static code list is easy to configure. These can either be set directly in the component configuration or in a json file in the application repository. Which method to use depends on the re-usability of -the code list. If multiple components should use the same code list, it is recommended to use the json file method. +the code list. If multiple components should use the same code list, it is recommended to use the [json file method](#from-json-files). + +Note that even though a static code list can be completely static, it is also possible to make it (a bit more) dynamic +by [filtering the options](../../functionality/filtering) using expressions. If you want even more flexibility, +you can also [create your own code-based code list](../dynamic). ## In component configuration diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md index b4ef3e8665..bf8375fc79 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md @@ -11,7 +11,11 @@ aliases: For enklere brukstilfeller er statiske kodelister det letteste å sette opp. Disse kan enten settes direkte i komponentkonfigurasjonen eller i en json-fil i app-repositoriet. Hvilken metode som bør brukes avhenger av gjenbruksbehovet til kodelisten. Hvis flere komponenter skal bruke samme kodeliste, anbefales det å -bruke metoden med json-filen. +[putte kodelisten i en json-fil](#fra-json-filer). + +Legg merke til at selv om en slik kodeliste kan være helt statisk, er det også mulig å gjøre den (litt mer) dynamisk +ved å [filtrere svaralternativene](../../functionality/filtering) ved hjelp av e uttrykk. Ønsker du enda mer +fleksiilitet, kan du også [lage en egen kodebasert kodeliste](../dynamic). ## I komponentkonfigurasjonen From c48c313a1c1566c81db05d4391ce4a49ef7f35ec Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 14:31:22 +0100 Subject: [PATCH 14/31] Rewriting section about repeating groups/structures --- .../sources/from-data-model/_index.en.md | 49 +++++++++---------- .../sources/from-data-model/_index.nb.md | 48 +++++++++--------- 2 files changed, 46 insertions(+), 51 deletions(-) diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md index 71eb43c1cb..6dc5f07152 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md @@ -7,40 +7,40 @@ aliases: - /altinn-studio/guides/development/options/repeating-group-codelists --- -Traditional options are based on resources fetched from the backend. -This approach differs a bit from this, as it enables setting up a direct connection from the options to the form data that is stored in app frontend. -A use case here would typically be if the user fills out a repeating list of data that should later be selected in a dropdown/checkbox/radiobutton. +In the previous section about [dynamic options](../dynamic) we covered how to write code on the backend to generate dynamic options for a component. You could use pass certain values from the data model to the backend to generate those options (via [query parameters](../dynamic#query-parameters)), but that approach scales poorly when the query parameters would end up changing the options frequently, i.e. when the options are functionally unique for some set of data in the data model. + +Another approach is to set up options based on a 'repeating group' in the data model. Such a repeating object in the data model could also represent a list of options for a dropdown, radio buttons, or checkboxes. This is especially useful combined with the [RepeatingGroup](../../../../../reference/ux/fields/grouping/repeating) component, as it allows the user to add and remove items from the list, and the options will automatically update. + +This functionality does not require the use of any `RepeatingGroup` component in the form layout, but it does require that the data model contains a repeating structure. ### Configuration -To set up options from the data model we have set up a new property on `RadioButtons`, `Checkboxes`, and `Dropdown`-components called `source`. +To set up options derived from the data model, use the `source` property in your component configuration. This property contains the fields `group`, `label`, and `value`. Example: ```json {hl_lines=["5-9"]} - { - "id": "dropdown-component-id", - "type": "Dropdown", - ... - "source": { - "group": "some.group", - "label": "dropdown.label", - "value": "some.group[{0}].someField" - } - }, +{ + "id": "dropdown-component-id", + "type": "Dropdown", + ... + "source": { + "group": "some.group", + "label": "dropdown.label", + "value": "some.group[{0}].someField" + } +} ``` Explanation: -- **group** - the group field in the data model to base the options on -- **label** - a reference to a text id to be used as the label for each iteration of the group, see more below. -- **value** - a reference to a field in the group that should be used as the option value. Notice that we set up this `[{0}]` syntax. Here the `{0}` will be replaced by each index of the group. - -Notice that the **value** field must be unique for each element. If the repeating group does not contain a field which is unique for each item it is recommended to add a field to the data model that can be used as identifier, for instance a GUID. +- **group** - the repeating group field in the data model to base the options on +- **label** - a reference to a text id to be used as the label for each option, see more below. +- **value** - a reference to a field in the group that should be used as the option value. Notice that we set up a placeholder `[{0}]` that will be replaced with the index of the repeating element. -As for the **label** property, we have to define a text resource that can be used as a label for each repetition of the group. -This follows similar syntax as the **value**, and will also be familiar if you have used [variables in text](/nb/altinn-studio/reference/ux/texts). +The **value** field must be unique for each element. If the repeating group does not contain a field which is unique for each item it is recommended to add a field to the data model that can be used as identifier, for instance a GUID. Non-unique values will be filtered out from all option lists, so not choosing a unique value can make it seem like the options are not being correctly populated. -Example text resource connected: +As for the **label** property, you have to define a text resource that can be used as a label for each option. +In the example below, other values from the repeating structure is used in the label via [variables in text](/altinn-studio/reference/ux/texts): ```json { @@ -62,7 +62,4 @@ Example text resource connected: } ] } -``` - -In the example above we have two parameters in the text which is referencing fields in the group. -We also recognize the `[{0}]` syntax in the `key` prop which enables the usage of this label for each index in the group. +``` \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md index a9a3554ec1..2bed6dd34a 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md @@ -7,40 +7,41 @@ aliases: - /nb/altinn-studio/guides/development/options/repeating-group-codelists --- -Tradisjonelle options baserer seg på ressurser hentet fra backend. -Denne måten å gjøre ting på endrer seg litt på dette, da det muliggjør å sette opp en direkte kobling fra komponent til skjemadata som ligger lagret i app frontend. -Et typisk bruksområde for dette er om brukeren fyller ut en liste med data som man senere i skjema ønsker å kunne velge mellom i en nedtrekksliste eller liknende. +I den forrige seksjonen om [dynamiske svaralternativer](../dynamic) beskrev vi hvordan man kan skrive kode på backend for å generere dynamiske svaralternativer for en komponent. Du kunne også sende visse verdier fra datamodellen til backend for å generere disse alternativene (via [spørringsparametere](../dynamic#spørringsparametere)). Denne fremgangsmåten skalerer dårlig når spørringsparametrene ender opp med å endre alternativene ofte, dvs. når alternativene er funksjonelt unike for en del av dataene i datamodellen. + +En annen tilnærming er å sette opp svaralternativer basert på en 'repeterende gruppe' i datamodellen. En slik repeterende struktur i datamodellen kan også representere en liste over alternativer for en nedtrekksliste, radioknapper eller avmerkingsbokser. Dette er spesielt nyttig i kombinasjon med [RepeatingGroup](../../../../../reference/ux/fields/grouping/repeating) komponenten, da det lar brukeren legge til og fjerne elementer fra listen, og alternativene vil automatisk oppdateres. + +Denne funksjonaliteten krever ikke bruk av noen `RepeatingGroup` komponent i skjemalayout, men det krever at datamodellen inneholder en repeterende struktur. ### Konfigurasjon -For å sette opp options fra datamodellen har vi laget en nytt objekt som kan brukes på komponentene `RadioButtons`, `Checkboxes` og `Dropdown` som vi har kalt `source`. -Dette nye objektet inneholder feltene `group`, `label` og `value`. Eksempel: +For å sette opp svaralternativer som hentes ut fra datamodellen brukes egenskapen `source`. +I dette objektet definerer man feltene `group`, `label` og `value`. Eksempel: ```json {hl_lines=["5-9"]} - { - "id": "dropdown-component-id", - "type": "Dropdown", - ... - "source": { - "group": "some.group", - "label": "dropdown.label", - "value": "some.group[{0}].someField" - } - }, +{ + "id": "dropdown-component-id", + "type": "Dropdown", + ... + "source": { + "group": "some.group", + "label": "dropdown.label", + "value": "some.group[{0}].someField" + } +} ``` Forklaring: -- **group** - gruppen i datamodellen man baserer options på. -- **label** - en referanse til en text id som brukes som label for hver iterasjon av gruppen. Se mer under. -- **value** - en referanse til det feltet i gruppen som skal bruke som option verdi. Legg merke til `[{0}]` syntaxen. Her vil `{0}` bli erstattet med den aktuelle indeksen for hvert element i gruppen. +- **group** - den repeterende strukturen i datamodellen man baserer svaralternativene på. +- **label** - en referanse til en tekstnøkkel som brukes som ledetekst for hvet svaralternativ. Se mer under. +- **value** - en referanse til det feltet i den repeterende strukturen som skal bruke som verdi, og dermed lagres når brukeren gjør et valg. Legg merke til at vi har fyllt inn `[{0}]` som vil bli erstattet med indeksen til det repeterende elementet. -Merk at **value** feltet må være unikt for hvert element. Om man ikke har et felt som er unik anbefales det å legge på et ekstra felt i datamodellen som kan benyttes som identifikator f.eks en GUID eller liknende. -For **label** feltet må vi definere en tekst ressurs som kan bli brukt som label for hver repetisjon av gruppen. -Dette følger samme syntax som **value**, og vil være kjent for deg om du har brukt [variabler i tekst](/nb/altinn-studio/reference/ux/texts). +Verdien hentet ut fra **value** må være unikt for hvert repeterende element. Om man ikke har et felt som er unikt per rad, anbefales det å legge på et ekstra felt i datamodellen som kan benyttes som identifikator f.eks en GUID eller liknende. Dersom verdien ikke er unik vil den bli filtrert bort fra alle svaralternativlister, og antallet svaralternativer tilgjengelige for brukeren kan da være noe lavere enn forventet ut fra datamodellen. -Eksempel: +For **label** feltet må vi definere en tekstressurs som kan bli brukt som ledetekst for hvert svaralternativ. +I eksempelet under, brukes andre verdier fra den repeterende strukturen i ledeteksten via [variabler i tekst](/nb/altinn-studio/reference/ux/texts): ```json { @@ -63,6 +64,3 @@ Eksempel: ] } ``` - -I dette eksempelet har vi satt opp to parametere i teksten som refererer til felter i gruppen. -Vi kjenner også igjen `[{0}]` syntaksen i `key` feltet som muliggjør gjenbruk av labelen for hver index i gruppen. From 559cec4950b685863fae43343b4ac0ba17d7b426 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 4 Dec 2024 15:09:07 +0100 Subject: [PATCH 15/31] Writing section about automatic cleanup --- .../automatic-cleanup/_index.en.md | 34 +++++++++++++++++++ .../automatic-cleanup/_index.nb.md | 34 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md index 6813eefb6e..86272cdce8 100644 --- a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md @@ -2,3 +2,37 @@ title: Automatic cleanup description: How unknown options are automatically removed from the data model --- + +Some options for components may be dynamic. Either directly via [dynamic options](../../sources/dynamic), +[options derived from a changing data model](../../sources/from-data-model), or by [static options](../../sources/static) +where some values may be [filtered](../filtering) out. + +When the options are dynamic, the data model may contain values that are no longer valid. This can happen if the user +(or prefill) has selected an option that is no longer available. In such cases, to avoid the data model from containing +invalid values, unknown options are automatically removed from the data model. + +## How it works + +When the form is loaded, the options for all components are fetched and compared to their values in the data model. Even +if a component is not visible (i.e. when on a page that is not currently shown), the app-frontend will still +check the options for that component and remove any values that are not in the options list. + +This has some implications that you should be aware of: +- If you configure multiple components pointing to the same field in the data model, the options for all those components + should be the same. If they are not, the data model will be cleaned up to only contain the options that are valid for + all components. +- If the component is not marked as `required`, the user can submit the form even if the value is removed from the data + model. If you want to ensure that the user selects a valid option, you should mark the component as required. + +## When it _doesn't_ happen + +- The automatic cleanup of unknown options currently only happens when the form is loaded via the app-frontend, + i.e. when the user opens the form in a browser. +- Automatic cleanup does not happen when the component is marked as `hidden`. For this reason you can also have + multiple components pointing to the same field in the data model, where some are hidden and some are visible. In such + cases, only the visible components will have their options checked and cleaned up. This is also the case if a component + is hidden due to being on a hidden page, or inside another hidden component. The term 'hidden' in this sense refers to + [dynamic expressions](../../../dynamics) used to hide components, not which components are currently visible on + the page. +- Removal of unknown values does not happen for the `FileUploadWithTag` component. +- Removal of unknown values does not happen for components configured with `renderAsSummary` set to `true`. \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md index fe0658e1b8..25b428d743 100644 --- a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md @@ -2,3 +2,37 @@ title: Automatisk opprydding description: Hvordan ukjente svaralternativer automatisk fjernes fra datamodellen --- + +Noen svaralternativer for komponenter kan være dynamiske. Enten direkte via [dynamiske svaralternativer](../../sources/dynamic), +[svaralternativer hentet fra en endrende datamodell](../../sources/from-data-model), eller ved [statiske svaralternativer](../../sources/static) +hvor noen verdier kan være [filtrert](../filtering) bort. + +Når svaralternativene er dynamiske, kan datamodellen inneholde verdier som ikke lenger er gyldige. Dette kan skje hvis +brukeren (eller forhåndsutfyllingen) har valgt et alternativ som ikke lenger er tilgjengelig. I slike tilfeller, for å +unngå at datamodellen inneholder ugyldige verdier, fjernes ukjente svaralternativer automatisk fra datamodellen. + +## Hvordan det fungerer + +Når skjemaet lastes, hentes svaralternativene for alle komponenter og sammenlignes med verdiene i datamodellen. Selv om +en komponent ikke er synlig (dvs. når på en side som for øyeblikket ikke vises), vil app-frontend fortsatt +sjekke svaralternativene for den komponenten og fjerne eventuelle verdier som ikke er i svaralternativlisten. + +Dette har noen implikasjoner som du bør være klar over: +- Hvis du konfigurerer flere komponenter som peker på det samme feltet i datamodellen, bør svaralternativene for alle + disse komponentene være de samme. Hvis de ikke er det, vil datamodellen ryddes opp for å kun inneholde de + svaralternativene som er gyldige for alle komponentene. +- Hvis komponenten ikke er merket som `required`, kan brukeren sende inn skjemaet selv om verdien fjernes fra + datamodellen. Hvis du vil sikre at brukeren velger et gyldig alternativ, bør du merke komponenten som påkrevd. + +## Når det _ikke_ skjer + +- Den automatiske oppryddingen av ukjente svaralternativer skjer for øyeblikket bare når skjemaet lastes via app-frontend, + dvs. når brukeren åpner skjemaet i en nettleser. +- Automatisk opprydding skjer ikke når komponenten er merket som `hidden`. Derfor kan du også ha flere + komponenter som peker på det samme feltet i datamodellen, hvor noen er skjulte og noen er synlige. I slike + tilfeller vil bare de synlige komponentene ha svaralternativene sjekket og ryddet opp. Dette er også tilfelle + hvis en komponent er skjult fordi den er på en skjult side, eller inne i en annen skjult komponent. + Begrepet 'skjult' i denne sammenhengen refererer til [dynamiske uttrykk](../../../dynamics) brukt for å skjule + komponenter, ikke hvilke komponenter som for øyeblikket er synlige på siden. +- Fjerning av ukjente verdier skjer ikke for komponenten `FileUploadWithTag`. +- Fjerning av ukjente verdier skjer ikke for komponenter konfigurert med `renderAsSummary` satt til `true`. \ No newline at end of file From eca72368e9e99b05d425c19586ae8b22d7d5623a Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Thu, 5 Dec 2024 09:44:55 +0100 Subject: [PATCH 16/31] Cleaning up in section about data-binding --- .../functionality/data-binding/_index.en.md | 42 ++++++++++------- .../functionality/data-binding/_index.nb.md | 45 +++++++++++-------- 2 files changed, 52 insertions(+), 35 deletions(-) diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md index f24876ff5d..38b3aa4f53 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md @@ -3,46 +3,54 @@ title: Data binding description: What can be stored in the data model --- -### Save label value in the datamodel -Sometimes you might wish to save the displayed value in the users chosen language to simplify creation of simple presentations of data without addtional lookups or a requirement to remember the label the user actually picked in case it have changed over time. +### Storing the label -This is performed by having a separate ``dataModelBindings`` with the key ``"label":`` in addition to ``"simpleBinding":`` +Components using options will usually only store the value of the selected option in the data model. While this is +usually sufficient, there are cases where you might want to store the label of the selected option as well. This can +be useful for displaying the selected option in a simple presentation of the data without additional lookups or if +you have a requirement to remember the label the user actually picked in case it has changed over time. When storing +the label in the data model, it will respect the users chosen language, look up the actual text from the text resources +and store the final value in the data model. -```json +This is configured by having a separate binding with the key `label`. The `label` binding should point to a field in the +data model of type `string`: + +```json {hl_lines=["6"]} { "id": "dropdown-component", "type": "Dropdown", "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype", - "label":"soknad.nyGaranti.loyvetypeLabel" + "simpleBinding": "municipality.value", + "label": "municipality.label" }, - "optionsId": "biler" + "optionsId": "municipalities" } ``` -### Store metadata for the parameters used to retrieve options in tha datamodel +### Storing metadata + +When fetching options, especially [shared common code lists](../../sources/shared), you might want to store some +metadata describing how the options were fetched. This can be useful for reconstructing the options after the form +has been submitted, as well as for logging purposes. -You can store metadata for the parameters used to retrieve options in the datamodel by setting the `metadata` property -on the components `dataModelBinding` property: +This can be configured by setting the `metadata` property on the components `dataModelBinding` property to a field +in the data model containing a `string` value: -```json +```json {hl_lines=["9"]} { "id": "some-dropdown-component", "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, "dataModelBindings": { "simpleBinding": "soknad.nyGaranti.loyvetype", - "metadata": "soknad.transportorOrgnummer" + "metadata": "soknad.nyGaranti.loyvetypeMetadata" }, "required": true, "optionsId": "loyvetyper", "mapping": { "soknad.transportorOrgnummer": "orgnummer" } -}, +} ``` This configuration will store the metadata of the retrieved options as a comma separated string in the -field `soknad.transportorOrgnummer` in the datamodel. +field `soknad.nyGaranti.loyvetypeMetadata` in the data model. \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md index 3983231966..e94696ed24 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md @@ -3,38 +3,46 @@ title: Dataknytning description: Hva kan lagres i datamodellen --- -### Lagre visningsverdi i datamodellen -Noen ganger ønsker man å lagre den viste verdien på brukerens språk i datamodellen for enklere å kunne bruke de lagrede dataene til å lagre enkle visninger uten å være avhengig av å gjøre et nytt oppslag for å få en visningsvennlig verdi. Det kan også brukes for å huske hva brukeren faktisk har sett når han valgte i tilfelle man endrer ordlyd for en verdi og vil ha logg for hva brukeren har sett. +### Lagring av ledetekst / visningsverdi -Dette gjøres ved å ha en egen ``dataModelBindings`` med navnet ``"label":`` i tillegg til en ``"simpleBinding":``. +Komponenter som bruker svaralternativer vil vanligvis bare lagre verdien av det valgte alternativet i datamodellen. +Dette er ofte tilstrekkelig, men i noen tilfeller kan det være nyttig å lagre ledeteksten til det valgte alternativet +også. For eksempel kan dette være nyttig om man trenger å vise det valgte alternativet i en enkel tekstvisning senere, +uten å måtte gjøre ytterligere oppslag. Det kan også være nyttig å huske hvilken ledetekst brukeren faktisk valgte i +tilfelle den endres over tid. Når ledeteksten lagres i datamodellen, vil den følge brukerens valgte språk, slå opp +teksten i tekstressursene og lagre den endelige verdien i datamodellen. -```json +Dette konfigureres ved å ha en separat binding med nøkkelen `label`. Denne bindingen må peke på et felt i +datamodellen av typen `string`: + +```json {hl_lines=["6"]} { - "id": "dropdown-komponent", + "id": "dropdown-component", "type": "Dropdown", "dataModelBindings": { - "simpleBinding": "soknad.nyGaranti.loyvetype", - "label":"soknad.nyGaranti.loyvetypeLabel" + "simpleBinding": "kommune.value", + "label": "kommune.label" }, - "optionsId": "biler" + "optionsId": "kommuner" } ``` -### Lagre metadata for parametrene som ble brukt til å hente options +### Lagring av metadata -Du kan lagre metadata for parameterene som ble brukt til å hente kodeliste i datamodellen ved å sette egenskapen `metadata` -på komponentens `dataModelBinding`-egenskap: +Når appen henter svaralternativer, spesielt [felles kodelister](../../sources/shared), kan det være nyttig å lagre +noen metadata som beskriver hvordan svaralternativene ble hentet. Dette kan være nyttig for å rekonstruere +svaralternativene etter at skjemaet er sendt inn, samt for logging. -```json +Dette kan konfigureres ved å sette `metadata`-egenskapen på komponentens `dataModelBinding`-egenskap til et felt i +datamodellen som inneholder en `string`-verdi: + +```json {hl_lines=["9"]} { "id": "some-dropdown-component", "type": "Dropdown", - "textResourceBindings": { - "title": "NyGarantiLoyvetype" - }, "dataModelBindings": { "simpleBinding": "soknad.nyGaranti.loyvetype", - "metadata": "soknad.transportorOrgnummer" + "metadata": "soknad.nyGaranti.loyvetypeMetadata" }, "required": true, "optionsId": "loyvetyper", @@ -44,5 +52,6 @@ på komponentens `dataModelBinding`-egenskap: } ``` -Denne konfigurasjonen vil lagre metadata for parameterene som ble brukt til å hente kodelisten som en kommaseparert -streng i feltet `soknad.transportorOrgnummer` i datamodellen. \ No newline at end of file +Denne konfigurasjonen vil nå lagre metadataen til de hentede svaralternativene som en kommaseparert streng i +feltet `soknad.nyGaranti.loyvetypeMetadata` i datamodellen. +` \ No newline at end of file From 1b93cc6994ce816f0a94381a3885a35747ee463d Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Thu, 5 Dec 2024 10:27:01 +0100 Subject: [PATCH 17/31] Writing about the storing the basic value in the data model --- .../functionality/data-binding/_index.en.md | 62 +++++++++++++++++++ .../functionality/data-binding/_index.nb.md | 62 +++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md index 38b3aa4f53..7873a65521 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md @@ -3,6 +3,68 @@ title: Data binding description: What can be stored in the data model --- +### Storing the chosen option + +{{}} +Below are some examples of setting up data binding for components using options. For some components, the setup will be +different, and it is recommended to look at the specific documentation for the component for more information. +{{}} + +Components using options must be set up to store the selected options in the data model. Usually, the component will +store the value of the selected option in the data model against a field of type `string`, set up in the component +configuration with the key `simpleBinding`: + +```json {hl_lines=["8"]} +{ + "id": "single-choice-component", + "type": "RadioButtons", + "textResourceBindings": { + "title": "Do you own a cat?" + }, + "dataModelBindings": { + "simpleBinding": "Submitter.HasCat" + }, + "options": [ + { "value": "y", "label": "Yes" }, + { "value": "n", "label": "No" } + ] +} +``` + +In the example above, the component will store the choice of whether the user owns a cat in the field `Submitter.HasCat` +in the data model. This field will get the value `y` if the user chooses "Yes" and `n` if the user chooses "No". + +For multi-choice components such as [`Checkboxes`](../../../../../reference/ux/components/checkboxes) and +[`MultipleSelect`](../../../../../reference/ux/components/multipleselect), the component will store a comma-separated +list of selected values in the data model. + +```json +{ + "id": "multi-choice-component", + "type": "Checkboxes", + "textResourceBindings": { + "title": "Which pets do you have?" + }, + "dataModelBindings": { + "simpleBinding": "Submitter.Pets" + }, + "options": [ + { "value": "cat", "label": "Cat" }, + { "value": "dog", "label": "Dog" }, + { "value": "fish", "label": "Fish" } + ] +} +``` + +In the example above, the component will store a comma-separated list of selected pets in the field `Submitter.Pets` in +the data model. If you choose "Cat" and "Fish", the field will get the value `"cat,fish"`. The order of the choices is +not guaranteed to be the same as the order of the options, nor the order the user chose them in. + +{{}} +Note that the value for each option must be unique, and if you use multi-choice components, none of the values can +contain a comma. +{{}} + ### Storing the label Components using options will usually only store the value of the selected option in the data model. While this is diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md index e94696ed24..1aeb4e0ab2 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md @@ -3,6 +3,68 @@ title: Dataknytning description: Hva kan lagres i datamodellen --- +### Lagring av valgt alternativ + +{{}} +Under følger noen eksempler på oppsett av dataknytning for komponenter som bruker svaralternativer. For noen komponenter +vil oppsettet være annerledes, og det anbefales å se på komponentens spesifikke dokumentasjon for mer informasjon. +{{}} + +Komponenter som bruker svaralternativer må settes opp til å lagre valgte alternativer i datamodellen. Vanligvis vil +komponenten lagre verdien av det valgte alternativet i datamodellen mot et felt av typen `string`, satt opp i +komponentens konfigurasjon med nøkkelen `simpleBinding`: + +```json {hl_lines=["8"]} +{ + "id": "single-choice-component", + "type": "RadioButtons", + "textResourceBindings": { + "title": "Eier du en katt?" + }, + "dataModelBindings": { + "simpleBinding": "Submitter.HasCat" + }, + "options": [ + { "value": "y", "label": "Ja" }, + { "value": "n", "label": "Nei" } + ] +} +``` + +I eksempelet over vil komponenten lagre valget av om brukeren eier en katt i feltet `Submitter.HasCat` i datamodellen. +Dette feltet får verdien `y` om brukeren velger "Ja" og `n` om brukeren velger "Nei". + +For flervalgskomponenter som f.eks. [`Checkboxes`](../../../../../reference/ux/components/checkboxes) og +[`MultipleSelect`](../../../../../reference/ux/components/multipleselect), vil komponenten lagre en kommaseparert +liste av valgte verdier i datamodellen. + +```json +{ + "id": "multi-choice-component", + "type": "Checkboxes", + "textResourceBindings": { + "title": "Hvilke kjæledyr har du?" + }, + "dataModelBindings": { + "simpleBinding": "Submitter.Pets" + }, + "options": [ + { "value": "cat", "label": "Katt" }, + { "value": "dog", "label": "Hund" }, + { "value": "fish", "label": "Fisk" } + ] +} +``` + +I eksempelet over vil komponenten lagre en kommaseparert liste av valgte kjæledyr i feltet `Submitter.Pets` i +datamodellen. Hvis du velger "Katt" og "Fisk", vil feltet få verdien `"cat,fish"`. Rekkefølgen på valgene er ikke +garantert å være den samme som rekkefølgen på svaralternativene, ei heller den rekkefølgen brukeren valgte dem i. + +{{}} +Legg merke til at verdien for hvert svaralternativ må være unik, og om man bruker flervalgskomponenter kan ingen +av verdiene inneholde et komma. +{{}} + ### Lagring av ledetekst / visningsverdi Komponenter som bruker svaralternativer vil vanligvis bare lagre verdien av det valgte alternativet i datamodellen. From 847898de15d8110e71e502db2141a2c7d85a2fde Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Thu, 5 Dec 2024 10:29:53 +0100 Subject: [PATCH 18/31] Weighting roughly according to the order the app developer should learn this stuff --- .../options/functionality/automatic-cleanup/_index.en.md | 1 + .../options/functionality/automatic-cleanup/_index.nb.md | 1 + .../development/options/functionality/data-binding/_index.en.md | 1 + .../development/options/functionality/data-binding/_index.nb.md | 1 + .../development/options/functionality/filtering/_index.en.md | 1 + .../development/options/functionality/filtering/_index.nb.md | 1 + .../development/options/functionality/preselection/_index.en.md | 1 + .../development/options/functionality/preselection/_index.nb.md | 1 + .../development/options/functionality/sorting/_index.en.md | 1 + .../development/options/functionality/sorting/_index.nb.md | 1 + .../guides/development/options/functionality/texts/_index.en.md | 1 + .../guides/development/options/functionality/texts/_index.nb.md | 1 + 12 files changed, 12 insertions(+) diff --git a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md index 86272cdce8..cd5d05520d 100644 --- a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.en.md @@ -1,6 +1,7 @@ --- title: Automatic cleanup description: How unknown options are automatically removed from the data model +weight: 100 --- Some options for components may be dynamic. Either directly via [dynamic options](../../sources/dynamic), diff --git a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md index 25b428d743..d90519997c 100644 --- a/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/automatic-cleanup/_index.nb.md @@ -1,6 +1,7 @@ --- title: Automatisk opprydding description: Hvordan ukjente svaralternativer automatisk fjernes fra datamodellen +weight: 100 --- Noen svaralternativer for komponenter kan være dynamiske. Enten direkte via [dynamiske svaralternativer](../../sources/dynamic), diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md index 7873a65521..0c6d1cf410 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.en.md @@ -1,6 +1,7 @@ --- title: Data binding description: What can be stored in the data model +weight: 50 --- ### Storing the chosen option diff --git a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md index 1aeb4e0ab2..417794e6c1 100644 --- a/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/data-binding/_index.nb.md @@ -1,6 +1,7 @@ --- title: Dataknytning description: Hva kan lagres i datamodellen +weight: 50 --- ### Lagring av valgt alternativ diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md index ab62490a78..527328ccf4 100644 --- a/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md @@ -1,4 +1,5 @@ --- title: Filtering description: Removing some options from the list +weight: 250 --- diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md index 33d4005333..9d602364df 100644 --- a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md @@ -1,4 +1,5 @@ --- title: Filtrering description: Fjerne noen alternativer fra listen +weight: 250 --- diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md index 7f4c2f421d..bbab734590 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md @@ -1,4 +1,5 @@ --- title: Pre-selection description: Making one option selected by default +weight: 200 --- diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md index 783ffc0027..01b61028a9 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md @@ -1,4 +1,5 @@ --- title: Forhåndsvalg description: Gjør et av alternativene forhåndsvalgt +weight: 200 --- diff --git a/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md b/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md index dd46afb040..79a861c8c7 100644 --- a/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md @@ -1,4 +1,5 @@ --- title: Sorting description: Sorting the options in the list +weight: 300 --- diff --git a/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md index f2f5749c4e..173fa947e0 100644 --- a/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md @@ -1,4 +1,5 @@ --- title: Sortering description: Sortere valgene i listen +weight: 300 --- diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md index 3c9e686fa4..5cf5a516eb 100644 --- a/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md @@ -1,6 +1,7 @@ --- title: Texts description: The different text properties that can be used for options +weight: 150 --- ## Description and HelpText diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md index ba0b69391b..686b164310 100644 --- a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md @@ -1,6 +1,7 @@ --- title: Tekster description: De ulike tekstegenskapene som kan brukes for svaralternativer +weight: 150 --- ## Beskrivelse og hjelpetekst From cb0668ed45ec659edbc1dc1ddd5f2842bea43580 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Thu, 5 Dec 2024 10:30:35 +0100 Subject: [PATCH 19/31] Preselection happens after filtering, but before sorting --- .../development/options/functionality/filtering/_index.en.md | 2 +- .../development/options/functionality/filtering/_index.nb.md | 2 +- .../development/options/functionality/preselection/_index.en.md | 2 +- .../development/options/functionality/preselection/_index.nb.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md index 527328ccf4..ab6c7f5208 100644 --- a/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md @@ -1,5 +1,5 @@ --- title: Filtering description: Removing some options from the list -weight: 250 +weight: 200 --- diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md index 9d602364df..86e2ccb992 100644 --- a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md @@ -1,5 +1,5 @@ --- title: Filtrering description: Fjerne noen alternativer fra listen -weight: 250 +weight: 200 --- diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md index bbab734590..cda0b2d788 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md @@ -1,5 +1,5 @@ --- title: Pre-selection description: Making one option selected by default -weight: 200 +weight: 250 --- diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md index 01b61028a9..411592b5a9 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md @@ -1,5 +1,5 @@ --- title: Forhåndsvalg description: Gjør et av alternativene forhåndsvalgt -weight: 200 +weight: 250 --- From ace0d0a463627e5643aeda5cc85501b2a3abfa88 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Mon, 9 Dec 2024 13:44:59 +0100 Subject: [PATCH 20/31] Writing about texts, adding a section about the label text and making configuration examples expandable. --- .../options/functionality/texts/_index.en.md | 48 +++++++++++++----- .../options/functionality/texts/_index.nb.md | 49 ++++++++++++++----- 2 files changed, 72 insertions(+), 25 deletions(-) diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md index 5cf5a516eb..5c0fc26515 100644 --- a/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md @@ -4,15 +4,36 @@ description: The different text properties that can be used for options weight: 150 --- -## Description and HelpText +## Label -`description` and `helpText` is supported by options in apps that use version v7.8.0 or higher. `description` and -`helpText` can be displayed by the components `RadioButtons` and `Checkboxes` by providing the option list with the -mentioned properties. +The most common text property for options is the `label`. The `label` is the text that is displayed to the user in the +UI (in contrast to the `value`, which is the value [stored in the data model](../data-binding)). +Both `label` and `value` are required properties for an option. -Descriptions and HelpTexts can be provided to `options` in the same way that a `label` is provided, in either static or -dynamic code lists. One can also use them in options based on repeating groups in the `source` attribute. +```json +[ + { "value": "norway", "label": "Norge" }, + { "value": "denmark", "label": "text.key.for.denmark" } +] +``` + +Labels, as with all texts, can either be plain text or a key pointing to a text resource. If the label is a key pointing +to a text resource, the text can change according to the selected language. + +The final text displayed to the user can [also be stored in the data model](../data-binding/#storing-the-label) if needed. +## Description and help text + +If you need to provide additional information about an option, you can use the `description` and `helpText` properties. +`description` and `helpText` can be displayed by the components `RadioButtons` and `Checkboxes`. + +Descriptions and help texts can be provided to `options` in the same way that a `label` is provided, via +[static](../../sources/static), [dynamic](../../sources/dynamic) +and [options from the data model](../../sources/from-data-model). + +Click on the headers below to expand the examples. + +{{% expandlarge id="static" header="Static JSON file or component configuration" %}} ```json [ { @@ -27,7 +48,9 @@ dynamic code lists. One can also use them in options based on repeating groups i } ] ``` +{{% /expandlarge %}} +{{% expandlarge id="dynamic" header="Dynamic options via C# code" %}} ```cs var options = new AppOptions { @@ -48,11 +71,9 @@ var options = new AppOptions } }; ``` +{{% /expandlarge %}} -Descriptions and help texts used in options based on repeating groups can be set up with dynamic text-resources in the -same way as labels, described in -[options based on repeating groups](repeating-group-codelists). - +{{% expandlarge id="from-data-model" header="Options based on repeating structures in the data model" %}} ```json { "id": "checkboxes-component-id", @@ -61,9 +82,10 @@ same way as labels, described in "source": { "group": "some.group", "label": "checkboxes.label", - "description": "checkboxes.descripiton", + "description": "checkboxes.description", "helpText": "checkboxes.helpText", "value": "some.group[{0}].someField" } -}, -``` \ No newline at end of file +} +``` +{{% /expandlarge %}} \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md index 686b164310..c04f928eb4 100644 --- a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md @@ -4,22 +4,44 @@ description: De ulike tekstegenskapene som kan brukes for svaralternativer weight: 150 --- +## Ledetekst + +Den vanligste tekstegenskapen for svaralternativer er `label`. `label` er teksten som vises for brukeren i +brukergrensesnittet (i motsetning til `value`, som er [verdien som lagres i datamodellen](../data-binding)). +Både `label` og `value` er påkrevde egenskaper for et svaralternativ. + +```json +[ + { "value": "norway", "label": "Norge" }, + { "value": "denmark", "label": "text.key.for.denmark" } +] +``` + +Ledetekster, som alle tekster, kan være enten ren tekst eller en nøkkel som peker til en tekstressurs. Hvis +`label` er en nøkkel som peker til en tekstressurs, kan teksten endres i henhold til brukerens valgte språk. + +Den endelige teksten som vises for brukeren kan [også lagres i datamodellen](../data-binding/#storing-the-label) hvis +det er nødvendig. + ## Beskrivelse og hjelpetekst -`description` og `helpText` støttes av kodelister i apper som bruker versjon 7.8.0 eller høyere. Beskrivelse og -hjelpetekst kan vises av komponentene `RadioButtons` og `Checkboxes` ved å sette attributtene i en `option` som -brukes av komponenten. +Hvis du trenger å gi ytterligere informasjon om et alternativ, kan du bruke egenskapene `description` og `helpText`. +`description` og `helpText` kan vises av komponentene `RadioButtons` og `Checkboxes`. -Beskrivelser og hjelpetekster kan gis til `options` på samme måte som en `label` er gitt, enten i statiske eller -dynamiske kodelister. Man kan også bruke dem i kodelister basert på repeterende grupper i `source`-attributten. +Beskrivelser og hjelpetekster kan spesifiseres på samme måte som en ledetekst (`label`) er gitt, enten i +[statiske](../../sources/static), [dynamiske](../../sources/dynamic) eller +[svaralternativer fra datamodellen](../../sources/from-data-model). +Klikk på overskriftene nedenfor for å utvide eksemplene. + +{{% expandlarge id="static" header="Statisk JSON-fil eller komponentkonfigurasjon" %}} ```json [ { "value": "norway", "label": "Norge", - "description": "This is a description", - "helpText": "This is a help text" + "description": "Dette er en beskrivelse", + "helpText": "Dette er en hjelpetekst" }, { "value": "denmark", @@ -27,7 +49,9 @@ dynamiske kodelister. Man kan også bruke dem i kodelister basert på repeterend } ] ``` +{{% /expandlarge %}} +{{% expandlarge id="dynamic" header="Dynamiske svaralternativer via C#-kode" %}} ```cs var options = new AppOptions { @@ -48,10 +72,9 @@ var options = new AppOptions } }; ``` +{{% /expandlarge %}} -Beskrivelser og hjelpetekster som brukes i kodelister basert på repeterende grupper kan settes opp med dynamiske -tekstressurser på samme måte som `label`, som beskrevet i -[kodelister fra repeterende grupper](repeating-group-codelists). +{{% expandlarge id="from-data-model" header="Svaralternativer basert på repeterende strukturer i datamodellen" %}} ```json { @@ -61,9 +84,11 @@ tekstressurser på samme måte som `label`, som beskrevet i "source": { "group": "some.group", "label": "checkboxes.label", - "description": "checkboxes.descripiton", + "description": "checkboxes.description", "helpText": "checkboxes.helpText", "value": "some.group[{0}].someField" } } -``` \ No newline at end of file +``` + +{{% /expandlarge %}} \ No newline at end of file From d6784c69841cc4495c1d338a3175b081cf3b79b9 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Mon, 9 Dec 2024 13:55:05 +0100 Subject: [PATCH 21/31] Adding a bit about expression support in options from repeating structures --- .../options/functionality/texts/_index.en.md | 10 +++++- .../options/functionality/texts/_index.nb.md | 10 ++++-- .../sources/from-data-model/_index.en.md | 31 +++++++++++++++++-- .../sources/from-data-model/_index.nb.md | 26 ++++++++++++++++ 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md index 5c0fc26515..e580221c9c 100644 --- a/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.en.md @@ -74,6 +74,9 @@ var options = new AppOptions {{% /expandlarge %}} {{% expandlarge id="from-data-model" header="Options based on repeating structures in the data model" %}} +Note that the properties `label`, `description`, and `helpText` can also be [dynamic expressions](../../../dynamics) +this mode. + ```json { "id": "checkboxes-component-id", @@ -83,7 +86,12 @@ var options = new AppOptions "group": "some.group", "label": "checkboxes.label", "description": "checkboxes.description", - "helpText": "checkboxes.helpText", + "helpText": [ + "if", ["equals", ["dataModel.someField"], "someValue"], + "checkboxes.helpText1", + "else", + "checkboxes.helpText2" + ], "value": "some.group[{0}].someField" } } diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md index c04f928eb4..31853cc508 100644 --- a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md @@ -75,6 +75,8 @@ var options = new AppOptions {{% /expandlarge %}} {{% expandlarge id="from-data-model" header="Svaralternativer basert på repeterende strukturer i datamodellen" %}} +Legg merke til at egenskapene `label`, `description` og `helpText` også kan være [dynamiske uttrykk](../../../dynamics) +i denne modusen. ```json { @@ -85,10 +87,14 @@ var options = new AppOptions "group": "some.group", "label": "checkboxes.label", "description": "checkboxes.description", - "helpText": "checkboxes.helpText", + "helpText": [ + "if", ["equals", ["dataModel.someField"], "someValue"], + "checkboxes.helpText1", + "else", + "checkboxes.helpText2" + ], "value": "some.group[{0}].someField" } } ``` - {{% /expandlarge %}} \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md index 6dc5f07152..4a0f480632 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md @@ -1,5 +1,5 @@ --- -title: Code lists based on repeating groups from the data model +title: Options from repeating structures linktitle: From data model description: Options made from a repeating structure in the data model weight: 150 @@ -62,4 +62,31 @@ In the example below, other values from the repeating structure is used in the l } ] } -``` \ No newline at end of file +``` + +### Expression support + +The properties `label`, `description`, and `helpText` can also be [dynamic expressions](../../../dynamics) in this mode. + +```json {hl_lines=["9-14"]} +{ + "id": "checkboxes-component-id", + "type": "Checkboxes", + ... + "source": { + "group": "some.group", + "label": "checkboxes.label", + "description": "checkboxes.description", + "helpText": [ + "if", ["equals", ["dataModel.someField"], "someValue"], + "checkboxes.helpText1", + "else", + "checkboxes.helpText2" + ], + "value": "some.group[{0}].someField" + } +``` + +In the example above, the `helpText` property is set up to show different help texts based on the value +of `someField` in the data model. If `someField` is equal to `someValue`, the help text will +be `checkboxes.helpText1`, otherwise it will be `checkboxes.helpText2`. \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md index 2bed6dd34a..5a79a5d696 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md @@ -64,3 +64,29 @@ I eksempelet under, brukes andre verdier fra den repeterende strukturen i ledete ] } ``` + +### Støtte for uttrykk + +Egenskapene `label`, `description` og `helpText` støtter også [dynamiske uttrykk](../../../dynamics) i denne modusen. + +```json {hl_lines=["9-14"]} +{ + "id": "checkboxes-component-id", + "type": "Checkboxes", + ... + "source": { + "group": "some.group", + "label": "checkboxes.label", + "description": "checkboxes.description", + "helpText": [ + "if", ["equals", ["dataModel.someField"], "someValue"], + "checkboxes.helpText1", + "else", + "checkboxes.helpText2" + ], + "value": "some.group[{0}].someField" + } +``` + +I eksempelet over er `helpText` satt opp til å vise forskjellige hjelpetekster basert på verdien av `someField` i datamodellen. +Hvis `someField` er lik `someValue`, vil hjelpeteksten være `checkboxes.helpText1`, ellers vil den være `checkboxes.helpText2`. From 690617f2d4c4293278896cfd6ed655ab4a95638a Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 10 Dec 2024 11:44:59 +0100 Subject: [PATCH 22/31] Writing about filtering --- .../functionality/filtering/_index.en.md | 104 ++++++++++++++++++ .../functionality/filtering/_index.nb.md | 103 +++++++++++++++++ .../functionality/filtering/filtering.gif | Bin 0 -> 314412 bytes 3 files changed, 207 insertions(+) create mode 100644 content/altinn-studio/guides/development/options/functionality/filtering/filtering.gif diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md index ab6c7f5208..b7551f9187 100644 --- a/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.en.md @@ -3,3 +3,107 @@ title: Filtering description: Removing some options from the list weight: 200 --- + +Filtering is a way to remove some of the options from the list. This can be useful if you want to limit which +options the user can choose from. + +Keep in mind that there are different approaches to making options dynamic: + +1. You can use [dynamics](../../../dynamics) to hide and show entirely different components based on a condition. These + components could be bound to the same location in the data model, but have different options. Note that + [automatic cleanup](../automatic-cleanup) may unexpectedly remove values from the data model when using this approach. + Test thoroughly to ensure form data is not lost when using this method. +2. By using [dynamic options](../../sources/dynamic) and passing query parameters to the backend, you can write custom code + to generate a different set of options based on those query parameters. This may be useful, but can cause lots of traffic + to the backend if the options are frequently changing. +3. Using [options from the data model](../../sources/from-data-model) you can set up options based on a repeating structure in + the data model. In combination with data processing on the backend, this can be a powerful way to create custom options + even when dynamic options based on query parameters would be problematic. + +Filtering options via the `optionFilter` property works with all of the above, and with +plain [static options](../../sources/static) as well. It makes it possible to use a [dynamic expression](../../../dynamics) +to filter out options based on the current state of the form. + +### Configuration + +In the example below, the `optionFilter` property is set to a dynamic expression that filters out the +option `should-be-removed`. Note that the `optionFilter` property accepts an expression for which options to keep, +so you should invert the logic to remove an option. + +The expression is evaluated for each option, and if it returns `true`, the option is _kept_. All other options are _removed_. + +```json {hl_lines=["10"]} +{ + "id": "dropdown-component-id", + "type": "Dropdown", + ... + "options": [ + { "value": "should-be-removed", "label": "Should be removed" }, + { "value": "red", "label": "Red" }, + { "value": "blue", "label": "Blue" } + ], + "optionFilter": ["notEquals", ["value"], "should-be-removed"] +} +``` + +The result of the above configuration will be a dropdown with two options: "Red" and "Blue". + +### The `value` function + +In the example above, the `value` function is used to access the value of the current option. This function can be used +with arguments to access other values in the option as well. + +- `["value"]` and `["value", "value"]` are equivalent, and will return the value of the current option. +- `["value", "label"]` will return the label of the current option. This label is the text given in the `label` property + of the option, before any text resources are looked up. +- `["value", "description"]` will return the [description of the current option](../texts), if set. +- `["value", "helpText"]` will return the [help text of the current option](../texts), if set. + + +### Example: Filtering duplicate options in a repeating group + +In the following animation, a `RepeatingGroup` component has been set up with a `Dropdown` component inside. +The `Dropdown` component has a `optionFilter` property that removes options that have already been used in +other rows in the repeating group. + +![Filtering options in a repeating group](filtering.gif) + +The configuration for this example is as follows: + +```json {hl_lines=["11-17"]} +{ + "id": "ingredientType", + "type": "Dropdown", + "textResourceBindings": { + "title": "Ingrediens" + }, + "dataModelBindings": { + "simpleBinding": "Ingredients.Type" + }, + "optionsId": "foods", + "optionFilter": [ + "or", + // Remove those that have been used elsewhere + ["not", ["commaContains", ["dataModel", "UsedTypes"], ["value"]]], + // But not if it's the currently chosen ingredient here + ["equals", ["component", "ingredientType"], ["value"]] + ] +} +``` + +A few things to note about the configuration: + +1. The already used types are stored in a comma-separated list in the `UsedTypes` field in the data model. This field + is updated using a [data processor](../../../../../reference/logic/dataprocessing) that finds all the unique types + in the `Ingredients` array. +2. If we just checked the `UsedTypes` field against the `value` of the current `Dropdown` component, as soon as an + ingredient was chosen, it would be removed from the list of options and + would [be automatically cleaned up](../automatic-cleanup). For this reason, we also check that the `value` is not + equal to the data set in the current `Dropdown` component. + +{{% notice warning %}} +The example above relies on saving the form data to the backend and running data processing to update +the `UsedTypes` field. For this reason, it is still fully possible to select the same ingredient in multiple rows +in the repeating group if you're fast enough. When using a method like this you should +also [implement validation](../../../../../reference/logic/validation) to catch any duplicates that might slip through. +{{% /notice %}} diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md index 86e2ccb992..1dffab4010 100644 --- a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md @@ -3,3 +3,106 @@ title: Filtrering description: Fjerne noen alternativer fra listen weight: 200 --- + +Filtrering gjør det mulig å fjerne noen av svaralternativene fra listen. Dette kan være nyttig hvis du vil begrense hvilke +alternativer brukeren kan velge mellom. + +Legg merke til at det allerede finnes flere måter å gjøre svaralternativene dynamiske på: + +1. Du kan bruke [dynamikk](../../../dynamics) for å skjule og vise helt forskjellige komponenter basert på en betingelse. Disse + komponentene kan være bundet til samme sted i datamodellen, men ha forskjellige svaralternativer. Merk at + [automatisk opprydding](../automatic-cleanup) kan fjerne verdier fra datamodellen når du bruker denne metoden. +2. Ved å bruke [dynamiske alternativer](../../sources/dynamic) og sende spørringsparametere til backenden, kan du skrive + kode for å generere et annet sett med alternativer basert på disse spørringsparametrene. Dette kan være nyttig, + men kan føre til mye nettverkstrafikk hvis alternativene og spørringsparametrene endres ofte. +3. Ved å bruke [svaralternativer fra en repeterende struktur i datamodellen](../../sources/from-data-model). I kombinasjon + med data prosessering på backenden, kan dette være en kraftig måte å lage egendefinerte svaralternativer på, selv når dynamiske + alternativer basert på spørringsparametre ville være problematisk. + +Filtrering av svaralternativer via `optionFilter`-egenskapen fungerer med alle de nevnte metodene, og med +vanlige [statiske svaralternativer](../../sources/static) også. +Dette gjør det mulig å bruke et [dynamisk uttrykk](../../../dynamics) for å filtrere ut svaralternativer basert +på den nåværende tilstanden i skjemaet. + +### Konfigurasjon + +I eksempelet under er `optionFilter`-egenskapen satt til et dynamisk uttrykk som filtrerer ut alternativet +`should-be-removed`. Merk at `optionFilter`-egenskapen settes opp med et uttrykk for hvilke alternativer som skal beholdes, +så du må snu om logikken for å fjerne et alternativ. + +Uttrykket evalueres for hvert svaralternativ, og hvis det returnerer `true`, beholdes alternativet. Alle andre alternativer fjernes. + +```json {hl_lines=["10"]} +{ + "id": "dropdown-component-id", + "type": "Dropdown", + ... + "options": [ + { "value": "should-be-removed", "label": "Denne blir fjernet" }, + { "value": "red", "label": "Rød" }, + { "value": "blue", "label": "Blå" } + ], + "optionFilter": ["notEquals", ["value"], "should-be-removed"] +} +``` + +Resultatet av konfigurasjonen over vil være en nedtrekksliste med to alternativer: "Rød" og "Blå". + +### `value`-funksjonen + +I eksempelet over brukes `value`-funksjonen til å få tilgang til verdien av det nåværende alternativet. +Denne funksjonen kan brukes med argumenter for å få tilgang til andre verdier i svaralternativet også. + +- `["value"]` og `["value", "value"]` er like, og vil returnere verdien av det nåværende alternativet. +- `["value", "label"]` vil returnere ledeteksten til det nåværende alternativet. Denne teksten er teksten som er gitt i + `label`-egenskapen til alternativet, før noen teksteressurser slås opp. +- `["value", "description"]` vil returnere [beskrivelsen av det nåværende alternativet](../texts), hvis satt. +- `["value", "helpText"]` vil returnere [hjelpeteksten til det nåværende alternativet](../texts), hvis satt. + +### Eksempel: Filtrere duplikate alternativer i en repeterende gruppe + +I animasjonen under er en `RepeatingGroup`-komponent satt opp med en `Dropdown`-komponent inni. Denne +`Dropdown`-komponenten har en `optionFilter`-egenskap som fjerner svaralternativer som allerede er brukt i andre +rader i den repeterende gruppen. + +![Filtrering av alternativer i en repeterende gruppe](filtering.gif) + +Konfigurasjonen for dette eksempelet er som følger: + +```json {hl_lines=["11-17"]} +{ + "id": "ingredientType", + "type": "Dropdown", + "textResourceBindings": { + "title": "Ingrediens" + }, + "dataModelBindings": { + "simpleBinding": "Ingredients.Type" + }, + "optionsId": "foods", + "optionFilter": [ + "or", + // Fjern de som har blitt brukt andre steder + ["not", ["commaContains", ["dataModel", "UsedTypes"], ["value"]]], + // Men ikke hvis det er den valgte ingrediensen her + ["equals", ["component", "ingredientType"], ["value"]] + ] +} +``` + +Noen ting å merke seg om konfigurasjonen: + +1. De allerede brukte ingrediens-typene lagres i en komma-separert liste i feltet `UsedTypes` i datamodellen. Dette feltet + oppdateres ved hjelp av [dataprosessering](../../../../../reference/logic/dataprocessing) som finner alle unike + ingredienstyper i `Ingredients`-lista. +2. Hvis vi bare sjekket `UsedTypes`-feltet mot `value`-verdien til den nåværende `Dropdown`-komponenten, ville alternativet + bli fjernet fra listen med en gang en ingrediens ble valgt, og verdien i datamodellen + ville da [blitt automatisk ryddet opp](../automatic-cleanup). Av denne grunn sjekker vi også at `value` ikke er lik + verdien til den nåværende `Dropdown`-komponenten. + +{{% notice warning %}} +Eksempelet ovenfor er avhengig av å lagre skjemadata til backenden og kjøre dataprosessering for å oppdatere +`UsedTypes`-feltet. Av denne grunn er det fortsatt fullt mulig å velge den samme ingrediensen i flere rader +i den repeterende gruppen hvis du er rask nok. Når du bruker en metode som dette bør du +også [implementere validering](../../../../../reference/logic/validation) for å fange opp eventuelle duplikate verdier. +{{% /notice %}} diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/filtering.gif b/content/altinn-studio/guides/development/options/functionality/filtering/filtering.gif new file mode 100644 index 0000000000000000000000000000000000000000..ae2234a9c3317133b84e4b716eafe3b5b969f8b4 GIT binary patch literal 314412 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

kIbM3}bOVO6>}IuvEa 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 Date: Tue, 10 Dec 2024 14:08:43 +0100 Subject: [PATCH 23/31] Writing about preselection, with a few warnings --- .../functionality/preselection/_index.en.md | 60 ++++++++++++++++++ .../functionality/preselection/_index.nb.md | 62 +++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md index cda0b2d788..332c343412 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md @@ -3,3 +3,63 @@ title: Pre-selection description: Making one option selected by default weight: 250 --- + +In some cases it is desirable that one of the options is pre-selected. There are different ways to achieve this. + +1. In the data model, you can [prefill the field](../../../prefill) with the desired value. Note that + the value must also belong to one of the valid options for components linked to this field in the data model, + otherwise the [value will be automatically cleaned up](../automatic-cleanup). +2. While filling out the form, you can also use [data processing](../../../../../reference/logic/dataprocessing) + to set the field to a desired pre-selected value. Beware that in some cases it is important to allow the user + to _not choose an option_. If the field is simply overwritten when it lacks a value, the user will not be able + to remove a pre-selected option using this approach. +3. Use the `preselectedOptionIndex` property, as described here. This allows the component itself to automatically choose + a numbered position in the list of options as pre-selected. + +### The `preselectedOptionIndex` property + +This property allows you to choose an option as pre-selected. It takes an integer as an argument, which is the index +of the option that should be pre-selected. The index starts at 0 for the first option, 1 for the second option, etc. + +```json +{ + "id": "my-component-id", + "type": "Checkboxes", + ... + "options": [ + { "value": "red", "label": "Red" }, + { "value": "blue", "label": "Blue" }, + { "value": "green", "label": "Green" } + ], + "preselectedOptionIndex": 1 +} +``` + +In the configuration above, "Blue" will be pre-selected when the component is displayed. The user can still choose +another option, and since this is a multi-select component, the user can also remove the pre-selection by clicking +the pre-selected option again. + +This functionality follows a set of rules: + +1. If the data model already has a value for the field, the pre-selection will not be set. +2. If a pre-selected value has already been set earlier (and e.g. deselected), this will not happen again as long as + the app is open in the browser. If the user reloads the page, the pre-selection may be set again. +3. The pre-selection is set as soon as the page has loaded and the components are ready, regardless of whether the + component is visible on the screen or not. +4. Pre-selected values are not set for components that are hidden using [dynamics](../../../dynamics). If + the component is shown again later, the pre-selection may be set. + +{{% notice warning %}} +There are situations where pre-selection with this property is not optimal, and can lead to situations that may be +perceived as erroneous: + +1. If an option is selected, the user deselects it, and reloads the form later, the pre-selection will be set again - + even if the component is on a page the user has already filled out and won't see again. +2. When the form is submitted via the API, pre-selections set with this property will have no effect. This property + requires that the form is open in the browser to work. +3. If the form is in a state where the data model is not writable or locked (e.g. in the PDF generator), + setting pre-selected values can lead to error messages and failed submissions. + +For these reasons, it is recommended to use this property with caution, and to consider one of the other alternative +methods for pre-selection described above. +{{% /notice %}} diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md index 411592b5a9..2c49ec1e96 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md @@ -3,3 +3,65 @@ title: Forhåndsvalg description: Gjør et av alternativene forhåndsvalgt weight: 250 --- + +Noen ganger er det ønskelig at et av svaralternativene er forhåndsvalgt. Det finnes ulike måter å oppnå dette på. + +1. I datamodellen kan du [forhåndsutfylle feltet](../../../prefill) med verdien som ønskes. Legg merke til at + verdien også må tilhøre en av de gyldige svaralternativene for komponenter knyttet mot dette feltet i datamodellen, + ellers vil [verdien bli ryddet bort automatisk](../automatic-cleanup). +2. Underveis i utfyllingen av et skjema kan man også bruke [dataprosessering](../../../../../reference/logic/dataprocessing) + for å sette feltet til en ønsket forhåndsvalgt verdi. I noen tilfeller er det riktignok viktig å tillate brukeren + å _ikke velge et alternativ_. Hvis feltet bare skrives over om det mangler en verdi, vil brukeren ikke kunne + fjerne et forhåndsvalgt alternativ. +3. Bruk av `preselectedOptionIndex`-egenskapen, som beskrevet her. Denne lar komponenten selv automatisk velge e + nummerert posisjon i listen av svaralternativer som forhåndsvalgt. + +### `preselectedOptionIndex`-egenskapen + +Denne egenskapen lar deg velge et svaralternativ som forhåndsvalgt. Den tar et heltall som argument, som er indeksen +til svaralternativet som skal være forhåndsvalgt. Indeksen starter på 0 for det første svaralternativet, 1 for det andre +osv. + +```json +{ + "id": "my-component-id", + "type": "Checkboxes", + ... + "options": [ + { "value": "red", "label": "Rød" }, + { "value": "blue", "label": "Blå" }, + { "value": "green", "label": "Grønn" } + ], + "preselectedOptionIndex": 1 +} +``` + +I konfigurasjonen over vil "Blå" være forhåndsvalgt når komponenten vises. Brukeren kan fortsatt velge et annet +alternativ, og ettersom dette er en flervalgskomponent, kan brukeren også fjerne forhåndsvalget ved å klikke på +det forhåndsvalgte alternativet igjen. + +Denne funksjonaliteten følger et sett med regler: + +1. Dersom datamodellen allerede har en verdi for feltet, vil ikke forhåndsvalget bli satt. +2. Dersom en forhåndsvalgt verdi allerede har blitt satt tidligere (og f.eks. valgt bort), vil dette ikke skje igjen så + lenge appen er åpen i nettleseren. Dersom brukeren laster siden på nytt, vil forhåndsvalget kunne bli satt igjen. +3. Forhåndsvalget settes med en gang siden har lastet og komponentene er klare, uavhengig av om komponenten vises + på skjermen eller ikke. +4. Forhåndsvalgte verdier blir ikke satt for komponenter som er skjult ved hjelp av [dynamikk](../../../dynamics). Om + komponenten senere blir vist igjen, vil forhåndsvalget kunne bli satt. + +{{% notice warning %}} +Det finnes situasjoner hvor forhåndsvalg med denne egenskapen ikke er optimalt, og kan føre til +situasjoner som kan oppleves som feil: + +1. Dersom et alternativ blir valgt, brukeren velger det bort igjen, og laster skjemaet på nytt senere vil forhåndsvalget + bli satt igjen - selv om komponenten er på en side lenge før den brukeren ser på, og ikke vil se igjen. +2. Når skjemaet sendes inn via API-et vil forhåndsvalg satt med denne egenskapen ikke ha noen effekt. Denne egenskapen + krever at skjemaet er åpent i nettleseren for å fungere. +3. Om skjemaet er i en tilstand hvor datamodellen ikke er skrivbar (f.eks. i PDF-generatoren), vil potensielt + setting av forhåndsvalgte verdier kunne føre til feilmeldinger og mislykket innsending dersom datamodellen ikke + allerede hadde en verdi. + +Av disse grunnene anbefales det å bruke denne egenskapen med forsiktighet, og å vurdere et av de andre alternativene +for forhåndsvalg som er beskrevet over. +{{% /notice %}} \ No newline at end of file From aa94ea5ad8e72ff15f7c0edc2298f9db0ebef96e Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 10 Dec 2024 14:41:35 +0100 Subject: [PATCH 24/31] More about preselection + section about sorting --- .../functionality/preselection/_index.en.md | 7 ++++ .../functionality/preselection/_index.nb.md | 8 ++++ .../functionality/sorting/_index.en.md | 37 +++++++++++++++++++ .../functionality/sorting/_index.nb.md | 37 +++++++++++++++++++ 4 files changed, 89 insertions(+) diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md index 332c343412..a04e66517c 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.en.md @@ -18,6 +18,12 @@ In some cases it is desirable that one of the options is pre-selected. There are ### The `preselectedOptionIndex` property +{{% notice info %}} +This property is available for most components support options, with the notable exception of the `FileUploadWithTag` +component. Only one option can be pre-selected at this time, and it is not possible to choose which option should +be pre-selected based on the value property of the option. +{{% /notice %}} + This property allows you to choose an option as pre-selected. It takes an integer as an argument, which is the index of the option that should be pre-selected. The index starts at 0 for the first option, 1 for the second option, etc. @@ -48,6 +54,7 @@ This functionality follows a set of rules: component is visible on the screen or not. 4. Pre-selected values are not set for components that are hidden using [dynamics](../../../dynamics). If the component is shown again later, the pre-selection may be set. +5. The preselected option is determined before [sorting](../sorting) is applied, but after [filtering](../filtering). {{% notice warning %}} There are situations where pre-selection with this property is not optimal, and can lead to situations that may be diff --git a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md index 2c49ec1e96..164db237c8 100644 --- a/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/preselection/_index.nb.md @@ -18,6 +18,12 @@ Noen ganger er det ønskelig at et av svaralternativene er forhåndsvalgt. Det f ### `preselectedOptionIndex`-egenskapen +{{% notice info %}} +Denne egenskapen er tilgjengelig for de fleste komponenter som støtter svaralternativer, med unntak av `FileUploadWithTag` +komponenten. Kun ett alternativ kan være forhåndsvalgt til enhver tid, og det er ikke mulig å velge hvilket alternativ +som skal være forhåndsvalgt basert på `value`-egenskapen til alternativet. +{{% /notice %}} + Denne egenskapen lar deg velge et svaralternativ som forhåndsvalgt. Den tar et heltall som argument, som er indeksen til svaralternativet som skal være forhåndsvalgt. Indeksen starter på 0 for det første svaralternativet, 1 for det andre osv. @@ -49,6 +55,8 @@ Denne funksjonaliteten følger et sett med regler: på skjermen eller ikke. 4. Forhåndsvalgte verdier blir ikke satt for komponenter som er skjult ved hjelp av [dynamikk](../../../dynamics). Om komponenten senere blir vist igjen, vil forhåndsvalget kunne bli satt. +5. Det forhåndsvalgte alternativet blir bestemt før [sortering](../sorting) blir utført, men etter [filtrering](../filtering). + {{% notice warning %}} Det finnes situasjoner hvor forhåndsvalg med denne egenskapen ikke er optimalt, og kan føre til diff --git a/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md b/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md index 79a861c8c7..c8710df0bb 100644 --- a/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md +++ b/content/altinn-studio/guides/development/options/functionality/sorting/_index.en.md @@ -3,3 +3,40 @@ title: Sorting description: Sorting the options in the list weight: 300 --- + +Options are usually displayed in the order they are defined in, but it is also possible to sort them alphabetically by +label. This can be useful to make it easier for the user to find the option they are looking for when the list does not +need to be in a specific order. + +Worth knowing: + +1. The sorting can change along the way if the user changes the language in the form. +2. The actual sorting is done after the [preselected value](../preselection) has been found. This means that + the sorting order should not affect which option is preselected. + +### Configuration + +The `sortOrder` property is optional, and can be set to one of the following values: + +- `asc` (ascending) - sorts in ascending order. Texts are sorted alphabetically from A to Z. +- `desc` (descending) - sorts in descending order. Texts are sorted alphabetically from Z to A. + +Example configuration: + +```json {hl_lines=[10]} +{ + "id": "sort-example", + "type": "RadioButtons", + "options": [ + { "value": "1", "label": "Cow" }, + { "value": "2", "label": "Alligator" }, + { "value": "3", "label": "Cat" }, + { "value": "4", "label": "Dog" } + ], + "sortOrder": "asc", + "preselectedOptionIndex": 0 +} +``` + +In the configuration above, the options will be sorted alphabetically in ascending order, and "Cow" will be preselected +even if it is not the first option displayed for the user. \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md index 173fa947e0..e51c860da8 100644 --- a/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/sorting/_index.nb.md @@ -3,3 +3,40 @@ title: Sortering description: Sortere valgene i listen weight: 300 --- + +Svaralternativer vises vanligvis i rekkefølgen de er definert i, men det er også mulig å sortere dem alfabetisk etter +ledetekst (`label`). Dette kan være nyttig for å gjøre det enklere for brukeren å finne det alternativet de leter etter +når listen ikke må være i en spesifikk rekkefølge. + +Verdt å vite: + +1. Sorteringen kan endre seg underveis dersom brukeren endrer språk i skjemaet. +2. Selve sorteringen gjøres etter [forhåndsvalgt verdi](../preselection) har blitt funnet. Det betyr at + sorteringsrekkefølgen ikke skal påvirke hvilket svaralternativ som er forhåndsvalgt. + +### Konfigurasjon + +Egenskapen `sortOrder` er valgfri, og kan settes til en av følgende verdier: + +- `asc` (ascending) - sorterer i stigende rekkefølge. Tekster sorteres alfabetisk fra A til Å. +- `desc` (descending) - sorterer i synkende rekkefølge. Tekster sorteres alfabetisk fra Å til A. + +Eksempel-konfigurasjon: + +```json {hl_lines=[10]} +{ + "id": "sort-example", + "type": "RadioButtons", + "options": [ + { "value": "1", "label": "Ku" }, + { "value": "2", "label": "Hest" }, + { "value": "3", "label": "Katt" }, + { "value": "4", "label": "Hund" } + ], + "sortOrder": "asc", + "preselectedOptionIndex": 0 +} +``` + +I konfigurasjonen over vil svaralternativene sorteres alfabetisk i stigende rekkefølge, og "Ku" vil være forhåndsvalgt +selv om det ikke er det første alternativet som vises for brukeren. \ No newline at end of file From a6b581313831fe72e6617901e9b845495cc9843b Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 10 Dec 2024 15:25:08 +0100 Subject: [PATCH 25/31] Fixing links --- .../app-dev-course-old/modul4/_index.en.md | 14 ++++---- .../app-dev-course-old/modul4/_index.nb.md | 14 ++++---- .../functionality/filtering/_index.nb.md | 2 +- .../options/functionality/texts/_index.nb.md | 2 +- .../options/sources/dynamic/_index.en.md | 6 ++-- .../options/sources/dynamic/_index.nb.md | 8 ++--- .../sources/from-data-model/_index.nb.md | 2 +- .../options/sources/shared/_index.en.md | 2 +- .../options/sources/shared/_index.nb.md | 2 +- .../reference/logic/expressions/_index.en.md | 34 +++++++++---------- .../reference/logic/expressions/_index.nb.md | 34 +++++++++---------- .../_common-props-content/options-page.en.md | 8 ++--- .../_common-props-content/options-page.nb.md | 8 ++--- .../_common-props-content/optionsId.en.md | 2 +- .../_common-props-content/optionsId.nb.md | 2 +- 15 files changed, 70 insertions(+), 70 deletions(-) diff --git a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md index cc51f784f6..6f0342250f 100644 --- a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md +++ b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md @@ -48,8 +48,8 @@ The municipality of Sogndal wishes to collect information on the newcomers emplo ### In Local Development environment 1. Create the directory `App/options` if it does not exist. -2. The municipality of Sogndal has created a [static code list](/altinn-studio/guides/development/options/static-codelists) for **industries**: [industry.json](../industry.json). Download the file and place it in `App/options`. -3. Set up the values in the code list for **Years in work force** as an [open dynamic code list](/altinn-studio/guides/development/options/dynamic-codelists) in `App/options` (follow the directions in the documentation). +2. The municipality of Sogndal has created a [static code list](/altinn-studio/guides/development/options/sources/static) for **industries**: [industry.json](../industry.json). Download the file and place it in `App/options`. +3. Set up the values in the code list for **Years in work force** as an [open dynamic code list](/altinn-studio/guides/development/options/sources/dynamic) in `App/options` (follow the directions in the documentation). Options: Label | Data value --------------|---------- @@ -62,8 +62,8 @@ The municipality of Sogndal wishes to collect information on the newcomers emplo ### Useful documentation -- [Static code lists](/altinn-studio/guides/development/options/static-codelists) -- [Dynamic code lists](/altinn-studio/guides/development/options/dynamic-codelists) +- [Static code lists](/altinn-studio/guides/development/options/sources/static) +- [Dynamic code lists](/altinn-studio/guides/development/options/sources/dynamic) ### Knowledge check {{% expandsmall id="m4t1q1" header="What is the difference between static and dynamic options?" %}} @@ -94,12 +94,12 @@ We want the user to be presented with a different set of options for the industr ### Tasks -1. [Send a dynamic query parameter](/altinn-studio/guides/development/options/#pass-query-parameters-when-fetching-options) with the Industry component based on the Sector. +1. [Send a dynamic query parameter](/altinn-studio/guides/development/options/sources/dynamic#query-parameters) with the Industry component based on the Sector. 2. Create a dynamic code list for _Industry_ with logic based on the value of the query parameter (hint: you can read the industry list from the JSON file). ### Useful documentation -- [How to pass query parameters when fetching options](/altinn-studio/guides/development/options/#pass-query-parameters-when-fetching-options) -- [How to configure dynamic code lists](/altinn-studio/guides/development/options/dynamic-codelists) +- [How to pass query parameters when fetching options](/altinn-studio/guides/development/sources/dynamic/#query-parameters) +- [How to configure dynamic code lists](/altinn-studio/guides/development/options/sources/dynamic) ### Knowledge check {{% expandsmall id="m4t2q1" header="If a code list is configured with a mapping to the data model, what happens when the relevant field changes value?" %}} diff --git a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md index e83df7cf94..150b8fdf18 100644 --- a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md +++ b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md @@ -47,8 +47,8 @@ Sogndal kommune ønsker å samle inn opplysninger om tilflytterens arbeidsituasj ### I lokalt utviklingsmiljø 1. Opprett mappen `App/options` hvis den ikke eksisterer. -2. Sogndal kommune har opprettet en [statisk kodeliste](/nb/altinn-studio/guides/development/options/static-codelists) for **bransjer**: [industry.json](../industry.json). Last ned filen og plasser den i `App/options`. -3. Sett opp alternativene for **År i arbeidslivet** som en [åpen dynamisk kodeliste](/nb/altinn-studio/guides/development/options/dynamic-codelists#åpne-dynamiske-kodelister) i mappen `App/options` (følg anvisning i dokumentasjonen). +2. Sogndal kommune har opprettet en [statisk kodeliste](/nb/altinn-studio/guides/development/options/sources/static) for **bransjer**: [industry.json](../industry.json). Last ned filen og plasser den i `App/options`. +3. Sett opp alternativene for **År i arbeidslivet** som en [åpen dynamisk kodeliste](/nb/altinn-studio/guides/development/options/sources/dynamic#åpne-dynamiske-kodelister) i mappen `App/options` (følg anvisning i dokumentasjonen). Svaralternativer: Label | Dataverdi -----------|---------- @@ -60,8 +60,8 @@ Sogndal kommune ønsker å samle inn opplysninger om tilflytterens arbeidsituasj ### Nyttig dokumentasjon -- [Statiske kodelister](/nb/altinn-studio/guides/development/options/static-codelists) -- [Dynamiske kodelister](/nb/altinn-studio/guides/development/options/dynamic-codelists) +- [Statiske kodelister](/nb/altinn-studio/guides/development/options/sources/static) +- [Dynamiske kodelister](/nb/altinn-studio/guides/development/options/sources/dynamic) ### Forståelsessjekk {{% expandsmall id="m4t1q1" header="Hva er forskjellen på statiske og dynamiske svaralternativer?" %}} @@ -95,12 +95,12 @@ basert på hvilken sektor de har krysset av for. ### Oppgaver -1. [Send en dynamisk query-parameter](/nb/altinn-studio/guides/development/options/#sende-med-spørringsparametere-ved-henting-av-en-kodeliste) med Bransje-komponenten basert på Sektor. +1. [Send en dynamisk query-parameter](/nb/altinn-studio/guides/development/options/sources/dynamic#spørringsparametre) med Bransje-komponenten basert på Sektor. 2. Lag en dynamisk kodeliste for _Bransje_ med logikk basert på verdien til query-parameteren (hint: du kan lese inn bransjelisten fra json-filen). ### Nyttig dokumentasjon -- [Hvordan sende med spørringsparametre ved henting av kodelister](/nb/altinn-studio/guides/development/options/#sende-med-spørringsparametere-ved-henting-av-en-kodeliste) -- [Hvordan sette opp dynamiske kodelister](/nb/altinn-studio/guides/development/options/dynamic-codelists) +- [Hvordan sende med spørringsparametre ved henting av kodelister](/nb/altinn-studio/guides/development/options/sources/dynamic#spørringsparametre) +- [Hvordan sette opp dynamiske kodelister](/nb/altinn-studio/guides/development/options/sources/dynamic) ### Forståelsessjekk {{% expandsmall id="m4t2q1" header="Om en kodeliste er satt opp med en mapping mot datamodellen, hva skjer når det aktuelle feltet endrer verdi?" %}} diff --git a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md index 1dffab4010..df209ffc1d 100644 --- a/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/filtering/_index.nb.md @@ -12,7 +12,7 @@ Legg merke til at det allerede finnes flere måter å gjøre svaralternativene d 1. Du kan bruke [dynamikk](../../../dynamics) for å skjule og vise helt forskjellige komponenter basert på en betingelse. Disse komponentene kan være bundet til samme sted i datamodellen, men ha forskjellige svaralternativer. Merk at [automatisk opprydding](../automatic-cleanup) kan fjerne verdier fra datamodellen når du bruker denne metoden. -2. Ved å bruke [dynamiske alternativer](../../sources/dynamic) og sende spørringsparametere til backenden, kan du skrive +2. Ved å bruke [dynamiske alternativer](../../sources/dynamic) og sende spørringsparametre til backenden, kan du skrive kode for å generere et annet sett med alternativer basert på disse spørringsparametrene. Dette kan være nyttig, men kan føre til mye nettverkstrafikk hvis alternativene og spørringsparametrene endres ofte. 3. Ved å bruke [svaralternativer fra en repeterende struktur i datamodellen](../../sources/from-data-model). I kombinasjon diff --git a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md index 31853cc508..8c1bf2c5b2 100644 --- a/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md +++ b/content/altinn-studio/guides/development/options/functionality/texts/_index.nb.md @@ -20,7 +20,7 @@ Både `label` og `value` er påkrevde egenskaper for et svaralternativ. Ledetekster, som alle tekster, kan være enten ren tekst eller en nøkkel som peker til en tekstressurs. Hvis `label` er en nøkkel som peker til en tekstressurs, kan teksten endres i henhold til brukerens valgte språk. -Den endelige teksten som vises for brukeren kan [også lagres i datamodellen](../data-binding/#storing-the-label) hvis +Den endelige teksten som vises for brukeren kan [også lagres i datamodellen](../data-binding/#lagring-av-ledetekst--visningsverdi) hvis det er nødvendig. ## Beskrivelse og hjelpetekst diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md index 7e81082ac4..70eab9f4bc 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md @@ -185,7 +185,7 @@ You can add both static and dynamic parameters by setting up `queryParameters` o In the example above the parameter `country=norway` will always be added to the request (this is entirely static and will not change). The parameter `orgnumber={nr}` will be added, where `{nr}` is the value of the field `some.orgnumber` in the data model. The parameter `adult={bool}` will be added, where `{bool}` will be either `true` or `false` based on whether the value of the field `some.age` is greater than or equal to 18. -More examples of expressions can be found in the [dynamics documentation](../../dynamics), and the full list of available functions can be found in the [expression reference overview](../../../../reference/logic/expressions). +More examples of expressions can be found in the [dynamics documentation](../../../dynamics), and the full list of available functions can be found in the [expression reference overview](../../../../../reference/logic/expressions). ### Based on the data model @@ -268,6 +268,6 @@ For a complete example of how this is setup see our [demo app.](https://altinn.s - The method `GetAppOptionsAsync` receives a language code in the `language` parameter. Language codes are based on ISO 639-1 or the W3C IANA Language Subtag Registry. The latter is built upon the ISO 639-1 standard but is guaranties uniques of the codes, whereas ISO 639-1 have conflicting usage for some codes. - An app can have many implementations of these interfaces, one for each option list. The correct implementation is found by looking at the code list identifier that is requested, and comparing it to the `Id` property in the implementation. This is also the identifier used in the `optionsId` property in the component configuration. Therefore, the `Id` property in the implementation must be unique per app. - It may be tempting to implement a dynamic option list that fetches data from the data model and produces the option list based on this. This is not recommended, as the app frontend only fetches the option list once for each unique set of query parameters. This means that the user interface showing the option list will not update in line with changes in the data model. - - An alternative is to use the functionality for [dynamic code lists based on the data model](../repeating-group-codelists), in some cases together with corresponding code in [DataProcessor](../../dynamics/data-processing). + - An alternative is to use the functionality for [dynamic code lists based on the data model](../from-data-model), in some cases together with corresponding code in [DataProcessor](../../../dynamics/data-processing). - Another alternative may be to use query parameters, as described above. -- If you use query parameters, it may be wise to consider how many unique combinations of parameters will typically be used in the app. If there are many, consider using a different approach such as fetching all data and filtering valid values in the frontend using [`optionFilter`](../filtering). Many different combinations of query parameters can lead to the app having to do a lot of unnecessary work to fetch new option lists every time the user makes a change in the form. +- If you use query parameters, it may be wise to consider how many unique combinations of parameters will typically be used in the app. If there are many, consider using a different approach such as fetching all data and filtering valid values in the frontend using [`optionFilter`](../../functionality/filtering). Many different combinations of query parameters can lead to the app having to do a lot of unnecessary work to fetch new option lists every time the user makes a change in the form. diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md index 34f6d30dc4..ecf158f945 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md @@ -186,7 +186,7 @@ Man kan legge til både statiske og dynamiske parametre ved å sette opp `queryP I eksempelet over vil parameteret `loyvetype=garanti` alltid bli sendt med (dette er helt statisk og vil ikke endre seg). Parameteret `orgnummer={nr}` vil bli sendt med, hvor `{nr}` er verdien på feltet `soknad.transportorOrgnummer` i datamodellen. Parameteret `myndig={bool}` vil bli sendt med, hvor `{bool}` blir enten `true` eller `false` basert på om verdien på feltet `soknad.alder` er større enn eller lik 18. -Flere eksempler på uttrykk finner du i [dokumentasjonen for dynamikk](../../dynamics), og den fullstendige oversikten over tilgjengelige funksjoner finner du i [referanseoversikten over uttrykk](../../../../reference/logic/expressions). +Flere eksempler på uttrykk finner du i [dokumentasjonen for dynamikk](../../../dynamics), og den fullstendige oversikten over tilgjengelige funksjoner finner du i [referanseoversikten over uttrykk](../../../../../reference/logic/expressions). ### Basert på datamodellen @@ -266,7 +266,7 @@ For et komplett eksempel kan du se vår [demo app.](https://altinn.studio/repos/ - Metoden `GetAppOptionsAsync` får inn en språkkode i parameteren `language`. Språkkoder bør baseres på ISO 639-1 standarden eller W3C IANA Language Subtag Registry standarden. Sistnevnte bygger på ISO 639-1 standarden men garanterer at alle kodene er unike, noe ISO 639-1 ikke gjør. - En app kan ha mange implementasjoner av disse interfacene, en for hver kodeliste. Den rette implementasjonen finnes gjennom å se på hvilken kodeliste-identifikator det spørres etter, og sammenlignes med `Id`-egenskapen i implementasjonen. Dette er også identifikatoren som brukes i `optionsId`-egenskapen i komponentkonfigurasjonen. Dermed må også `Id`-egenskapen i implementasjonen være unik per app. -- Det kan være fristende å sette opp en dynamisk og sikret kodeliste hvor man henter ut data fra datamodellen og produserer kodelisten basert på dette. Dette er ikke anbefalt, da appens frontend bare henter kodelisten en gang hvor hvert unike sett med spørringsparametere. Det betyr at visningen av kodelisten ikke vil oppdatere seg i tråd med endringene i datamodellen. - - Et alternativ er å bruke funksjonaliteten for [dynamiske kodelister basert på datamodell](../repeating-group-codelists), i noen tilfeller sammen med tilsvarende kode i [DataProcessor](../../dynamics/data-processing). +- Det kan være fristende å sette opp en dynamisk og sikret kodeliste hvor man henter ut data fra datamodellen og produserer kodelisten basert på dette. Dette er ikke anbefalt, da appens frontend bare henter kodelisten en gang hvor hvert unike sett med spørringsparametre. Det betyr at visningen av kodelisten ikke vil oppdatere seg i tråd med endringene i datamodellen. + - Et alternativ er å bruke funksjonaliteten for [dynamiske kodelister basert på datamodell](../from-data-model), i noen tilfeller sammen med tilsvarende kode i [DataProcessor](../../../dynamics/data-processing). - Et annet alternativ kan være å bruke spørringsparametre, som beskrevet over. -- Dersom man bruker spørringsparametre, kan det være lurt å tenke gjennom hvor mange unike kombinasjoner av parametre som typisk vil bli brukt i appen. Hvis det er mange, kan det være lurt å vurdere å bruke en annen tilnærming, som for eksempel å hente ut all data og filtrere gyldige verdier i frontend ved hjelp av [`optionFilter`](../filtering). Mange ulike kombinasjoner av spørringsparametre kan før til at appen må gjøre mye unødvendig arbeid for å hente nye kodeliste-verdier hver gang brukeren gjør en endring i skjemaet. \ No newline at end of file +- Dersom man bruker spørringsparametre, kan det være lurt å tenke gjennom hvor mange unike kombinasjoner av parametre som typisk vil bli brukt i appen. Hvis det er mange, kan det være lurt å vurdere å bruke en annen tilnærming, som for eksempel å hente ut all data og filtrere gyldige verdier i frontend ved hjelp av [`optionFilter`](../../functionality/filtering). Mange ulike kombinasjoner av spørringsparametre kan før til at appen må gjøre mye unødvendig arbeid for å hente nye kodeliste-verdier hver gang brukeren gjør en endring i skjemaet. \ No newline at end of file diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md index 5a79a5d696..d25de60ecd 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md @@ -7,7 +7,7 @@ aliases: - /nb/altinn-studio/guides/development/options/repeating-group-codelists --- -I den forrige seksjonen om [dynamiske svaralternativer](../dynamic) beskrev vi hvordan man kan skrive kode på backend for å generere dynamiske svaralternativer for en komponent. Du kunne også sende visse verdier fra datamodellen til backend for å generere disse alternativene (via [spørringsparametere](../dynamic#spørringsparametere)). Denne fremgangsmåten skalerer dårlig når spørringsparametrene ender opp med å endre alternativene ofte, dvs. når alternativene er funksjonelt unike for en del av dataene i datamodellen. +I den forrige seksjonen om [dynamiske svaralternativer](../dynamic) beskrev vi hvordan man kan skrive kode på backend for å generere dynamiske svaralternativer for en komponent. Du kunne også sende visse verdier fra datamodellen til backend for å generere disse alternativene (via [spørringsparametre](../dynamic#spørringsparametre)). Denne fremgangsmåten skalerer dårlig når spørringsparametrene ender opp med å endre alternativene ofte, dvs. når alternativene er funksjonelt unike for en del av dataene i datamodellen. En annen tilnærming er å sette opp svaralternativer basert på en 'repeterende gruppe' i datamodellen. En slik repeterende struktur i datamodellen kan også representere en liste over alternativer for en nedtrekksliste, radioknapper eller avmerkingsbokser. Dette er spesielt nyttig i kombinasjon med [RepeatingGroup](../../../../../reference/ux/fields/grouping/repeating) komponenten, da det lar brukeren legge til og fjerne elementer fra listen, og alternativene vil automatisk oppdateres. diff --git a/content/altinn-studio/guides/development/options/sources/shared/_index.en.md b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md index d3caa4b80e..28f9bff468 100644 --- a/content/altinn-studio/guides/development/options/sources/shared/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md @@ -40,7 +40,7 @@ These code lists are created as a separate [NuGet package](https://www.nuget.org You can do this either using [Altinn Studio](https://altinn.studio) and configure the *code list ID* of your component in the user interface. - Or you can configure the component by editing the `optionsId` property in FormLayout.json according to the [documentation](/altinn-studio/guides/development/options/#connect-the-component-to-options-code-list). + Or you can configure the component by editing the `optionsId` property for the component in the layout file. ## Custom Configuration While the configuration mentioned above, where you use the method `services.AddAltinnCodelists();`, will register all available code lists with default values, there may be cases where you want to customize the configuration of a code list. The examples below will vary slightly depending on the source of the code list, as different sources offer different options. diff --git a/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md index dca88b30c2..29faa34945 100644 --- a/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md @@ -41,7 +41,7 @@ aliases: Du kan gjøre dette enten ved hjelp av [Altinn Studio](https://altinn.studio) og konfigurere *Kodeliste-ID* for komponenten din i brukergrensesnittet. - Eller du kan konfigurere komponenten ved å redigere egenskapen `optionsId` i FormLayout.json i henhold til [dokumentasjonen](/altinn-studio/guides/development/options/#connect-the-component-to-options-code-list). + Eller du kan konfigurere komponenten ved å redigere egenskapen `optionsId` form komponenten i layout-filen. ## Tilpasset konfigurasjon Mens konfigurasjonen nevnt ovenfor der du kaller `services.AddAltinnCodelists();` vil legge til alle tilgjengelige kodelister med standardverdier, kan det være tilfeller der du ønsker å tilpasse konfigurasjonen av en kodeliste. Eksemplene under vil variere noe avhengig av kilden til kodelisten siden de ulike kildene tilbyr ulike muligheter. diff --git a/content/altinn-studio/reference/logic/expressions/_index.en.md b/content/altinn-studio/reference/logic/expressions/_index.en.md index 98338381b2..98ad125fd4 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.en.md +++ b/content/altinn-studio/reference/logic/expressions/_index.en.md @@ -146,23 +146,23 @@ And for a person who is 15 years old (or younger, such as a 4-year-old), the tex Dynamic expressions are currently available for use in these properties, as defined in [layout files](../../ux/pages). -| Components | Property | Expected Value | Frontend | Backend | -|--------------------------------------------------------------------------------------------------------|-------------------------------|----------------------------|----------|---------| -| [Pages/layouts](#showhide-entire-pages) | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | -| All | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | -| Form components | `required` | [Boolean](#boolean-values) | ✅ | ✅ | -| Form components | `readOnly` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolean](#boolean-values) | ✅ | ❌ | -| [Option based components](../../../guides/development/options/static-codelists) | `source.label` | [String](#strings) | ✅ | ❌ | -| [Option based components](../../../guides/development/options/static-codelists) | `source.description` | [String](#strings) | ✅ | ❌ | -| [Option based components](../../../guides/development/options/static-codelists) | `source.helpText` | [String](#strings) | ✅ | ❌ | -| [Option based components](../../../guides/development/options/dynamic-codelists/#based-on-expressions) | `queryParameters.[*]` | [String](#strings) | ✅ | ❌ | -| All | `textResourceBindings.[*]` \* | [String](#strings) | ✅ | ❌ | +| Components | Property | Expected Value | Frontend | Backend | +|------------------------------------------------------------------------------------------------------------|-------------------------------|----------------------------|----------|---------| +| [Pages/layouts](#showhide-entire-pages) | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | +| All | `hidden` | [Boolean](#boolean-values) | ✅ | ✅ | +| Form components | `required` | [Boolean](#boolean-values) | ✅ | ✅ | +| Form components | `readOnly` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Repeating groups](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolean](#boolean-values) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/sources/from-data-model/#expression-support) | `source.label` | [String](#strings) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/sources/from-data-model/#expression-support) | `source.description` | [String](#strings) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/sources/from-data-model/#expression-support) | `source.helpText` | [String](#strings) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/sources/dynamic/#based-on-expressions) | `queryParameters.[*]` | [String](#strings) | ✅ | ❌ | +| All | `textResourceBindings.[*]` \* | [String](#strings) | ✅ | ❌ | \* = The values that can be overridden with textResourceBindings vary from component to component, but will work wherever used. For repeating groups, you can find [more information here](../../ux/fields/grouping/repeating#textresourcebindings) diff --git a/content/altinn-studio/reference/logic/expressions/_index.nb.md b/content/altinn-studio/reference/logic/expressions/_index.nb.md index 94e0d687c1..0c17934871 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.nb.md +++ b/content/altinn-studio/reference/logic/expressions/_index.nb.md @@ -141,23 +141,23 @@ Og for en person som er 15 år (eller yngre, som f.eks. en 4-åring), returneres Dynamiske uttrykk er foreløpig tilgjengelig for bruk i disse egenskapene, som definert i [layout-filer](../../ux/pages). -| Komponenter | Egenskap | Forventet verdi | Frontend | Backend | -|----------------------------------------------------------------------------------------------------------|-------------------------------|----------------------------|----------|---------| -| [Sider/layouts](#viseskjule-hele-sider) | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| Alle | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| Skjemakomponenter | `required` | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| Skjemakomponenter | `readOnly` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | -| [Kodelistebaserte komponenter](../../../guides/development/options/static-codelists) | `source.label` | [Streng](#strenger) | ✅ | ❌ | -| [Kodelistebaserte komponenter](../../../guides/development/options/static-codelists) | `source.description` | [Streng](#strenger) | ✅ | ❌ | -| [Kodelistebaserte komponenter](../../../guides/development/options/static-codelists) | `source.helpText` | [Streng](#strenger) | ✅ | ❌ | -| [Kodelistebaserte komponenter](../../../guides/development/options/dynamic-codelists/#basert-på-uttrykk) | `queryParameters.[*]` | [Streng](#strenger) | ✅ | ❌ | -| Alle | `textResourceBindings.[*]` \* | [Streng](#strenger) | ✅ | ❌ | +| Komponenter | Egenskap | Forventet verdi | Frontend | Backend | +|-----------------------------------------------------------------------------------------------------------------|-------------------------------|----------------------------|----------|---------| +| [Sider/layouts](#viseskjule-hele-sider) | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| Alle | `hidden` | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| Skjemakomponenter | `required` | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| Skjemakomponenter | `readOnly` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `hiddenRow` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.addButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.deleteButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.alertOnDelete` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Repeterende grupper](../../ux/fields/grouping/repeating) | `edit.saveAndNextButton` | [Boolsk](#boolske-verdier) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/sources/from-data-model/#støtte-for-uttrykk) | `source.label` | [Streng](#strenger) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/sources/from-data-model/#støtte-for-uttrykk) | `source.description` | [Streng](#strenger) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/sources/from-data-model/#støtte-for-uttrykk) | `source.helpText` | [Streng](#strenger) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/sources/dynamic/#basert-på-uttrykk) | `queryParameters.[*]` | [Streng](#strenger) | ✅ | ❌ | +| Alle | `textResourceBindings.[*]` \* | [Streng](#strenger) | ✅ | ❌ | \* = Hvilke verdier man kan overstyre med textResourceBindings varierer fra komponent til komponent, men vil fungere på alle steder der det brukes. TextResourceBindings for repeterende grupper finner diff --git a/content/altinn-studio/reference/ux/components/_common-props-content/options-page.en.md b/content/altinn-studio/reference/ux/components/_common-props-content/options-page.en.md index 576ed3ccfc..cb79626729 100644 --- a/content/altinn-studio/reference/ux/components/_common-props-content/options-page.en.md +++ b/content/altinn-studio/reference/ux/components/_common-props-content/options-page.en.md @@ -13,7 +13,7 @@ Options can be added manually or by using [code lists](/altinn-studio/guides/dev {{< property-docs prop="source" >}} **Documentation for code lists** -- [Link a Component to a Code List](/altinn-studio/guides/development/options/#connect-the-component-to-options-code-list) -- [Static Code Lists](/altinn-studio/guides/development/options/static-codelists/) -- [Dynamic Code Lists](/altinn-studio/guides/development/options/dynamic-codelists/) -- [Code lists based on repeating groups from the data model](/altinn-studio/guides/development/options/repeating-group-codelists/) \ No newline at end of file +- [Link a Component to a Code List](/altinn-studio/guides/development/options/) +- [Static Code Lists](/altinn-studio/guides/development/options/sources/static/) +- [Dynamic Code Lists](/altinn-studio/guides/development/options/sources/dynamic/) +- [Code lists based on repeating groups from the data model](/altinn-studio/guides/development/options/sources/from-data-model/) \ No newline at end of file diff --git a/content/altinn-studio/reference/ux/components/_common-props-content/options-page.nb.md b/content/altinn-studio/reference/ux/components/_common-props-content/options-page.nb.md index 6a2597ad86..cfc0ce5796 100644 --- a/content/altinn-studio/reference/ux/components/_common-props-content/options-page.nb.md +++ b/content/altinn-studio/reference/ux/components/_common-props-content/options-page.nb.md @@ -13,7 +13,7 @@ Alternativer (options) kan legges til manuelt eller ved hjelp av [kodelister](/n {{< property-docs prop="source" >}} **Dokumentasjon for kodelister** -- [Koble en komponent til kodeliste](/nb/altinn-studio/guides/development/options/#koble-en-komponent-til-en-kodeliste) -- [Statiske kodelister](/nb/altinn-studio/guides/development/options/static-codelists/) -- [Dynamiske kodelister](/nb/altinn-studio/guides/development/options/dynamic-codelists/) -- [Dynamiske kodelister fra repeterede grupper i datamodellen](/nb/altinn-studio/guides/development/options/repeating-group-codelists/) \ No newline at end of file +- [Koble en komponent til kodeliste](/nb/altinn-studio/guides/development/options/) +- [Statiske kodelister](/nb/altinn-studio/guides/development/options/sources/static/) +- [Dynamiske kodelister](/nb/altinn-studio/guides/development/options/sources/dynamic/) +- [Dynamiske kodelister fra repeterede grupper i datamodellen](/nb/altinn-studio/guides/development/options/sources/from-data-model/) \ No newline at end of file diff --git a/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md b/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md index 22d0093a3a..24933ddd91 100644 --- a/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md +++ b/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md @@ -19,7 +19,7 @@ To add options from a code list, select "Kodeliste" and enter a code list ID.
-If you wish to [secure dynamic code lists](/altinn-studio/guides/development/options/dynamic-codelists/#secured-dynamic-options), you can check this option: +If you wish to [secure dynamic code lists](/altinn-studio/guides/development/options/sources/dynamic/#secured-options), you can check this option: {{% image file="component-settings/secure.png" %}} diff --git a/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.nb.md b/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.nb.md index bced1ee81c..2e048584fb 100644 --- a/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.nb.md +++ b/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.nb.md @@ -19,7 +19,7 @@ For å legge til alternativer fra en kodeliste, velg 'Kodeliste' og angi en kode
-Om du ønsker å [sikre dynamiske kodelister](/nb/altinn-studio/guides/development/options/dynamic-codelists/#sikrede-dynamiske-kodelister) kan du huke av for dette: +Om du ønsker å [sikre dynamiske kodelister](/nb/altinn-studio/guides/development/options/sources/dynamic/#sikrede-kodelister) kan du huke av for dette: {{% image file="component-settings/secure.png" %}} From 87c9b28f6ad4427705b9c21e8ca3d63ff3e2b5a6 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Tue, 10 Dec 2024 15:32:24 +0100 Subject: [PATCH 26/31] Fixing more links --- .../getting-started/app-dev-course-old/modul4/_index.en.md | 2 +- .../getting-started/app-dev-course-old/modul4/_index.nb.md | 2 +- .../guides/development/options/sources/dynamic/_index.en.md | 2 +- .../guides/development/options/sources/dynamic/_index.nb.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md index 6f0342250f..02be19e9d5 100644 --- a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md +++ b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.en.md @@ -98,7 +98,7 @@ We want the user to be presented with a different set of options for the industr 2. Create a dynamic code list for _Industry_ with logic based on the value of the query parameter (hint: you can read the industry list from the JSON file). ### Useful documentation -- [How to pass query parameters when fetching options](/altinn-studio/guides/development/sources/dynamic/#query-parameters) +- [How to pass query parameters when fetching options](/altinn-studio/guides/development/options/sources/dynamic/#query-parameters) - [How to configure dynamic code lists](/altinn-studio/guides/development/options/sources/dynamic) ### Knowledge check diff --git a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md index 150b8fdf18..9b19b83408 100644 --- a/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md +++ b/content/altinn-studio/getting-started/app-dev-course-old/modul4/_index.nb.md @@ -48,7 +48,7 @@ Sogndal kommune ønsker å samle inn opplysninger om tilflytterens arbeidsituasj 1. Opprett mappen `App/options` hvis den ikke eksisterer. 2. Sogndal kommune har opprettet en [statisk kodeliste](/nb/altinn-studio/guides/development/options/sources/static) for **bransjer**: [industry.json](../industry.json). Last ned filen og plasser den i `App/options`. -3. Sett opp alternativene for **År i arbeidslivet** som en [åpen dynamisk kodeliste](/nb/altinn-studio/guides/development/options/sources/dynamic#åpne-dynamiske-kodelister) i mappen `App/options` (følg anvisning i dokumentasjonen). +3. Sett opp alternativene for **År i arbeidslivet** som en [åpen dynamisk kodeliste](/nb/altinn-studio/guides/development/options/sources/dynamic#åpne-kodelister) i mappen `App/options` (følg anvisning i dokumentasjonen). Svaralternativer: Label | Dataverdi -----------|---------- diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md index 70eab9f4bc..8c7856917c 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md @@ -268,6 +268,6 @@ For a complete example of how this is setup see our [demo app.](https://altinn.s - The method `GetAppOptionsAsync` receives a language code in the `language` parameter. Language codes are based on ISO 639-1 or the W3C IANA Language Subtag Registry. The latter is built upon the ISO 639-1 standard but is guaranties uniques of the codes, whereas ISO 639-1 have conflicting usage for some codes. - An app can have many implementations of these interfaces, one for each option list. The correct implementation is found by looking at the code list identifier that is requested, and comparing it to the `Id` property in the implementation. This is also the identifier used in the `optionsId` property in the component configuration. Therefore, the `Id` property in the implementation must be unique per app. - It may be tempting to implement a dynamic option list that fetches data from the data model and produces the option list based on this. This is not recommended, as the app frontend only fetches the option list once for each unique set of query parameters. This means that the user interface showing the option list will not update in line with changes in the data model. - - An alternative is to use the functionality for [dynamic code lists based on the data model](../from-data-model), in some cases together with corresponding code in [DataProcessor](../../../dynamics/data-processing). + - An alternative is to use the functionality for [dynamic code lists based on the data model](../from-data-model), in some cases together with corresponding code in [DataProcessor](../../../../../reference/logic/dataprocessing). - Another alternative may be to use query parameters, as described above. - If you use query parameters, it may be wise to consider how many unique combinations of parameters will typically be used in the app. If there are many, consider using a different approach such as fetching all data and filtering valid values in the frontend using [`optionFilter`](../../functionality/filtering). Many different combinations of query parameters can lead to the app having to do a lot of unnecessary work to fetch new option lists every time the user makes a change in the form. diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md index ecf158f945..cb0a919b45 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md @@ -267,6 +267,6 @@ For et komplett eksempel kan du se vår [demo app.](https://altinn.studio/repos/ - Metoden `GetAppOptionsAsync` får inn en språkkode i parameteren `language`. Språkkoder bør baseres på ISO 639-1 standarden eller W3C IANA Language Subtag Registry standarden. Sistnevnte bygger på ISO 639-1 standarden men garanterer at alle kodene er unike, noe ISO 639-1 ikke gjør. - En app kan ha mange implementasjoner av disse interfacene, en for hver kodeliste. Den rette implementasjonen finnes gjennom å se på hvilken kodeliste-identifikator det spørres etter, og sammenlignes med `Id`-egenskapen i implementasjonen. Dette er også identifikatoren som brukes i `optionsId`-egenskapen i komponentkonfigurasjonen. Dermed må også `Id`-egenskapen i implementasjonen være unik per app. - Det kan være fristende å sette opp en dynamisk og sikret kodeliste hvor man henter ut data fra datamodellen og produserer kodelisten basert på dette. Dette er ikke anbefalt, da appens frontend bare henter kodelisten en gang hvor hvert unike sett med spørringsparametre. Det betyr at visningen av kodelisten ikke vil oppdatere seg i tråd med endringene i datamodellen. - - Et alternativ er å bruke funksjonaliteten for [dynamiske kodelister basert på datamodell](../from-data-model), i noen tilfeller sammen med tilsvarende kode i [DataProcessor](../../../dynamics/data-processing). + - Et alternativ er å bruke funksjonaliteten for [dynamiske kodelister basert på datamodell](../from-data-model), i noen tilfeller sammen med tilsvarende kode i [DataProcessor](../../../../../reference/logic/dataprocessing). - Et annet alternativ kan være å bruke spørringsparametre, som beskrevet over. - Dersom man bruker spørringsparametre, kan det være lurt å tenke gjennom hvor mange unike kombinasjoner av parametre som typisk vil bli brukt i appen. Hvis det er mange, kan det være lurt å vurdere å bruke en annen tilnærming, som for eksempel å hente ut all data og filtrere gyldige verdier i frontend ved hjelp av [`optionFilter`](../../functionality/filtering). Mange ulike kombinasjoner av spørringsparametre kan før til at appen må gjøre mye unødvendig arbeid for å hente nye kodeliste-verdier hver gang brukeren gjør en endring i skjemaet. \ No newline at end of file From 6ba083b5461cc515bfee31fba70a6b2b0d52c25c Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Wed, 11 Dec 2024 15:18:52 +0100 Subject: [PATCH 27/31] Adding docs about argv and value --- .../reference/logic/expressions/_index.en.md | 98 +++++++++++++------ .../reference/logic/expressions/_index.nb.md | 97 ++++++++++++------ 2 files changed, 132 insertions(+), 63 deletions(-) diff --git a/content/altinn-studio/reference/logic/expressions/_index.en.md b/content/altinn-studio/reference/logic/expressions/_index.en.md index 98ad125fd4..c620df63ae 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.en.md +++ b/content/altinn-studio/reference/logic/expressions/_index.en.md @@ -261,38 +261,40 @@ Here we find the closest `age` component `age-1`, which is _36_, Kari's age. These functions are available for use in expressions: -| Function Name | Parameters | Return Value | Frontend | Backend | -|----------------------------------------------|--------------------------------------------------------------------------------------------------| ------------------------------------ | -------- | ------- | -| [`equals`](#func-equals) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`notEquals`](#func-equals) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`not`](#func-not) | [Boolean](#boolean-values) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`greaterThan`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`greaterThanEq`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`lessThan`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`lessThanEq`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`concat`](#func-concat) | None or multiple [strings](#strings) | [String](#strings) | ✅ | ✅ | -| [`and`](#func-and) | One or more [boolean values](#boolean-values) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`or`](#func-and) | One or more [boolean values](#boolean-values) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`if`](#func-if) | [See detailed description](#func-if) | [See detailed description](#func-if) | ✅ | ✅ | -| [`contains`](#func-contains-not-contains) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`notContains`](#func-contains-not-contains) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`commaContains`](#func-commaContains) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`startsWith`](#func-starts-ends-with) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`endsWith`](#func-starts-ends-with) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | -| [`lowerCase`](#func-lowerCase-upperCase) | [String](#strings) | [String](#strings) | ✅ | ✅ | -| [`upperCase`](#func-lowerCase-upperCase) | [String](#strings) | [String](#strings) | ✅ | ✅ | -| [`stringLength`](#func-stringLength) | [String](#strings) | [Number](#numbers) | ✅ | ✅ | -| [`text`](#func-text) | [String](#strings) | [String](#strings) | ✅ | ❌ | -| [`language`](#func-language) | None | [String](#strings) | ✅ | ❌ | -| [`displayValue`](#func-displayValue) | [String](#strings) | [String](#strings) | ✅ | ❌ | -| [`round`](#func-round) | [Number](#numbers), optional [Number](#numbers) | [String](#strings) | ✅ | ✅ | -| [`instanceContext`](#func-instancecontext) | [String](#strings) | [String](#strings) | ✅ | ✅ | -| [`frontendSettings`](#func-frontendsettings) | [String](#strings) | [String](#strings) | ✅ | ✅ | -| [`dataModel`](#func-datamodel) | [String](#strings) | [String](#strings) | ✅ | ✅ | -| [`component`](#func-component) | [String](#strings) | [String](#strings) | ✅ | ✅ | -| [`formatDate`](#func-formatDate) | [String](#strings), optional [String](#strings) | [String](#strings) | ✅ | ❌ | -| [`linkToPage`](#func-linkToPage) | [String](#strings), [String](#strings) | [String](#strings) | ✅ | ❌ | -| [`linkToComponent`](#func-linkToComponent) | [String](#strings), [String](#strings) | [String](#strings) | ✅ | ❌ | +| Function Name | Parameters | Return Value | Frontend | Backend | +|----------------------------------------------|-------------------------------------------------|--------------------------------------|----------|---------| +| [`equals`](#func-equals) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`notEquals`](#func-equals) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`not`](#func-not) | [Boolean](#boolean-values) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`greaterThan`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`greaterThanEq`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`lessThan`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`lessThanEq`](#func-gt) | [Number](#numbers), [Number](#numbers) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`concat`](#func-concat) | None or multiple [strings](#strings) | [String](#strings) | ✅ | ✅ | +| [`and`](#func-and) | One or more [boolean values](#boolean-values) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`or`](#func-and) | One or more [boolean values](#boolean-values) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`if`](#func-if) | [See detailed description](#func-if) | [See detailed description](#func-if) | ✅ | ✅ | +| [`contains`](#func-contains-not-contains) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`notContains`](#func-contains-not-contains) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`commaContains`](#func-commaContains) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`startsWith`](#func-starts-ends-with) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`endsWith`](#func-starts-ends-with) | [String](#strings), [String](#strings) | [Boolean](#boolean-values) | ✅ | ✅ | +| [`lowerCase`](#func-lowerCase-upperCase) | [String](#strings) | [String](#strings) | ✅ | ✅ | +| [`upperCase`](#func-lowerCase-upperCase) | [String](#strings) | [String](#strings) | ✅ | ✅ | +| [`stringLength`](#func-stringLength) | [String](#strings) | [Number](#numbers) | ✅ | ✅ | +| [`text`](#func-text) | [String](#strings) | [String](#strings) | ✅ | ❌ | +| [`language`](#func-language) | None | [String](#strings) | ✅ | ❌ | +| [`displayValue`](#func-displayValue) | [String](#strings) | [String](#strings) | ✅ | ❌ | +| [`round`](#func-round) | [Number](#numbers), optional [Number](#numbers) | [String](#strings) | ✅ | ✅ | +| [`instanceContext`](#func-instancecontext) | [String](#strings) | [String](#strings) | ✅ | ✅ | +| [`frontendSettings`](#func-frontendsettings) | [String](#strings) | [String](#strings) | ✅ | ✅ | +| [`dataModel`](#func-datamodel) | [String](#strings) | [String](#strings) | ✅ | ✅ | +| [`component`](#func-component) | [String](#strings) | [String](#strings) | ✅ | ✅ | +| [`formatDate`](#func-formatDate) | [String](#strings), optional [String](#strings) | [String](#strings) | ✅ | ❌ | +| [`linkToPage`](#func-linkToPage) | [String](#strings), [String](#strings) | [String](#strings) | ✅ | ❌ | +| [`linkToComponent`](#func-linkToComponent) | [String](#strings), [String](#strings) | [String](#strings) | ✅ | ❌ | +| [`argv`](#func-argv) | [Number](#numbers) | [String](#strings) | ✅ | ✅ | +| [`value`](#func-value) | optional [String](#strings) | [String](#strings) | ✅ | ❌ | Detailed descriptions and examples @@ -834,6 +836,38 @@ When clicked, this link will take the user to the page the component is on and f {{% /expandlarge %}} +{{% expandlarge id="func-argv" header="argv" %}} +The `argv` function can be used to retrieve arguments sent to the expression. This is currently only available for +[expression-based validation](../validation/expression-validation). + +The function takes 1 argument, which is the index of the argument you want to retrieve. The index starts at 0. + +```json +["argv", 0] +``` +{{% /expandlarge %}} + +{{% expandlarge id="func-value" header="value" %}} +Like `argv`, the `value` function is also a method for retrieving arguments sent to the expression. The function can be used +without arguments to retrieve a value, or with an argument to retrieve other types of values. This is currently available +for [filtering of options](../../../guides/development/options/functionality/filtering) and will soon be available +as an alternative to `argv` in [expression-based validation](../validation/expression-validation). + +```json +["value"] +``` + +This expression retrieves the value of the option (if used in filtering options). In other contexts, this expression currently +returns an error message. + +```json +["value", "label"] +``` + +The expression above retrieves the text of the option (if used in filtering options). In other contexts, this expression +returns an error message. +{{% /expandlarge %}} + ## Data Types Expressions in the functions expect that the arguments sent in have a specific type. If an argument sent in has a diff --git a/content/altinn-studio/reference/logic/expressions/_index.nb.md b/content/altinn-studio/reference/logic/expressions/_index.nb.md index 0c17934871..7fe66286e6 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.nb.md +++ b/content/altinn-studio/reference/logic/expressions/_index.nb.md @@ -259,37 +259,39 @@ Hva vil resultatet bli i de forskjellige eksemplene? Her er svarene: Disse funksjonene er tilgjengelige for bruk i uttrykk: | Funksjonsnavn | Parametre | Returverdi | Frontend | Backend | -| -------------------------------------------- | -------------------------------------------------- | ------------------------------------ | -------- | ------- | -| [`equals`](#func-equals) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`notEquals`](#func-equals) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`not`](#func-not) | [Boolsk](#boolske-verdier) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`greaterThan`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`greaterThanEq`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`lessThan`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`lessThanEq`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`concat`](#func-concat) | Ingen eller flere [strenger](#strenger) | [Streng](#strenger) | ✅ | ✅ | -| [`and`](#func-and) | En eller flere [boolske verdier](#boolske-verdier) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`or`](#func-and) | En eller flere [boolske verdier](#boolske-verdier) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`if`](#func-if) | [Se detaljert beskrivelse](#func-if) | [Se detaljert beskrivelse](#func-if) | ✅ | ✅ | -| [`contains`](#func-contains-not-contains) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`notContains`](#func-contains-not-contains) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`commaContains`](#func-commaContains) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`startsWith`](#func-starts-ends-with) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`endsWith`](#func-starts-ends-with) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | -| [`lowerCase`](#func-lowerCase-upperCase) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | -| [`upperCase`](#func-lowerCase-upperCase) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | -| [`stringLength`](#func-stringLength) | [Streng](#strenger) | [Tall](#tall) | ✅ | ✅ | -| [`text`](#func-text) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | -| [`language`](#func-language) | Ingenting | [Streng](#strenger) | ✅ | ❌ | -| [`displayValue`](#func-displayValue) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | -| [`round`](#func-round) | [Tall](#tall), valgfritt [Tall](#tall) | [Streng](#strenger) | ✅ | ✅ | -| [`instanceContext`](#func-instancecontext) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | -| [`frontendSettings`](#func-frontendsettings) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | -| [`dataModel`](#func-datamodel) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | -| [`component`](#func-component) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | -| [`formatDate`](#func-formatDate) | [Streng](#strenger), valgfri [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | -| [`linkToPage`](#func-linkToPage) | [Streng](#strenger), [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | -| [`linkToComponent`](#func-linkToComponent) | [Streng](#strenger), [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | +|----------------------------------------------|----------------------------------------------------|--------------------------------------|----------|---------| +| [`equals`](#func-equals) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`notEquals`](#func-equals) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`not`](#func-not) | [Boolsk](#boolske-verdier) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`greaterThan`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`greaterThanEq`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`lessThan`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`lessThanEq`](#func-gt) | [Tall](#tall), [Tall](#tall) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`concat`](#func-concat) | Ingen eller flere [strenger](#strenger) | [Streng](#strenger) | ✅ | ✅ | +| [`and`](#func-and) | En eller flere [boolske verdier](#boolske-verdier) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`or`](#func-and) | En eller flere [boolske verdier](#boolske-verdier) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`if`](#func-if) | [Se detaljert beskrivelse](#func-if) | [Se detaljert beskrivelse](#func-if) | ✅ | ✅ | +| [`contains`](#func-contains-not-contains) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`notContains`](#func-contains-not-contains) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`commaContains`](#func-commaContains) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`startsWith`](#func-starts-ends-with) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`endsWith`](#func-starts-ends-with) | [Streng](#strenger), [Streng](#strenger) | [Boolsk](#boolske-verdier) | ✅ | ✅ | +| [`lowerCase`](#func-lowerCase-upperCase) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | +| [`upperCase`](#func-lowerCase-upperCase) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | +| [`stringLength`](#func-stringLength) | [Streng](#strenger) | [Tall](#tall) | ✅ | ✅ | +| [`text`](#func-text) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | +| [`language`](#func-language) | Ingenting | [Streng](#strenger) | ✅ | ❌ | +| [`displayValue`](#func-displayValue) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | +| [`round`](#func-round) | [Tall](#tall), valgfritt [Tall](#tall) | [Streng](#strenger) | ✅ | ✅ | +| [`instanceContext`](#func-instancecontext) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | +| [`frontendSettings`](#func-frontendsettings) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | +| [`dataModel`](#func-datamodel) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | +| [`component`](#func-component) | [Streng](#strenger) | [Streng](#strenger) | ✅ | ✅ | +| [`formatDate`](#func-formatDate) | [Streng](#strenger), valgfri [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | +| [`linkToPage`](#func-linkToPage) | [Streng](#strenger), [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | +| [`linkToComponent`](#func-linkToComponent) | [Streng](#strenger), [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | +| [`argv`](#func-argv) | [Tall](#tall) | [Streng](#strenger) | ✅ | ✅ | +| [`value`](#func-value) | valgfri [Streng](#strenger) | [Streng](#strenger) | ✅ | ❌ | Detaljerte beskrivelser og eksempler @@ -826,6 +828,39 @@ Resultatet vil bli `
Date: Mon, 16 Dec 2024 16:24:30 +0100 Subject: [PATCH 28/31] Clarifying the terms, changing the titles --- .../guides/development/options/_index.en.md | 24 ++++++++++++++++--- .../guides/development/options/_index.nb.md | 23 ++++++++++++++++-- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/content/altinn-studio/guides/development/options/_index.en.md b/content/altinn-studio/guides/development/options/_index.en.md index ef782fb754..0cc3c482e8 100644 --- a/content/altinn-studio/guides/development/options/_index.en.md +++ b/content/altinn-studio/guides/development/options/_index.en.md @@ -1,7 +1,7 @@ --- -title: Options (code lists) +title: Code lists and options linktitle: Options -description: How to configure Options / Code lists for an app? +description: How to set up code lists for components that use options toc: true weight: 40 aliases: @@ -9,7 +9,25 @@ aliases: - /altinn-studio/reference/data/options --- -Several of the form components in Altinn 3 use options. The concept referred to as options is sometimes also called _code lists_. +Several of the form components in Altinn 3 use options. By options, we mean a list of choices that can be selected by +the user. In the most basic use-cases you might [set up a list of options directly in the component configuration](sources/static), +but often you'll want to fetch the options from a _code list_. + +### Terms + +There are subtle differences between the terms _options_ and _code lists_: + +- **Options**: A list of choices that can be selected by the user. Think of the contacts in your phone. When you use + your contact list to dial someone, you are selecting from a list of options, and your phone uses the selected value + (the phone number) to dial the person. +- **Code list**: A list of codes and their corresponding value and texts. Think of + the [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country codes. This list contains codes (like `NO` + or `SE`) and their corresponding labels (like `Norway` or `Sweden`). + +When selecting a value from (for example) a Dropdown component, you are selecting from a list of _options_, which +might be sourced from a _code list_. In that case, options is _what they are_, and a code list is _where they came from_. + +### Supported components The following components support options: diff --git a/content/altinn-studio/guides/development/options/_index.nb.md b/content/altinn-studio/guides/development/options/_index.nb.md index 91ba0f4a32..59d5f13320 100644 --- a/content/altinn-studio/guides/development/options/_index.nb.md +++ b/content/altinn-studio/guides/development/options/_index.nb.md @@ -1,5 +1,5 @@ --- -title: Svaralternativer +title: Kodelister og svaralternativer linktitle: Svaralternativer description: Hvordan konfigurere svaralternativer for en app toc: true @@ -9,7 +9,26 @@ aliases: - /nb/altinn-studio/reference/data/options --- -Flere av skjemakomponentene i Altinn 3 bruker svaralternativer. Konseptet omtalt som svaralternativer kalles av og til også for _kodelister_ (eller _code lists_ og _options_ på engelsk). +Flere av skjemakomponentene i Altinn 3 bruker svaralternativer. Med svaralternativer mener vi en liste med valg som +kan velges av brukeren. I de enkleste tilfellene kan du +[sette opp en liste med svaralternativer direkte i konfigurasjonen til komponenten](sources/static) +men ofte kommer svaralternativene til å hentes fra en _kodeliste_. + +### Begreper + +Det er noen små forskjeller mellom begrepene _svaralternativer_ og _kodelister_: + +- **Svaralternativer**: En liste med valg som kan velges av brukeren. Tenk på kontaktene i telefonen din. Når du bruker + kontaktlisten din for å ringe noen, velger du fra en liste med svaralternativer, og telefonen din bruker den valgte verdien + (telefonnummeret) for å ringe personen. +- **Kodeliste**: En liste med koder og deres tilhørende verdier og tekster. Tenk på + [ISO 3166-1](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) landskoder. Denne listen inneholder koder (som `NO` + eller `SE`) og deres tilhørende ledetekst (som `Norge` eller `Sverige`). + +Når du velger en verdi fra (for eksempel) en nedtrekksliste, velger du fra en liste med _svaralternativer_, som +kan være hentet fra en _kodeliste_. I dette tilfellet er svaralternativer _hva de er_, og en kodeliste er _hvor de kommer fra_. + +### Støttede komponenter Følgende komponenter støtter svaralternativer: From 35bbac7d57e4a2f34f6e170718aa45c60d73431d Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Mon, 16 Dec 2024 16:43:36 +0100 Subject: [PATCH 29/31] Trying to use the correct terms the right places --- .../development/options/sources/_index.en.md | 10 +++--- .../development/options/sources/_index.nb.md | 14 ++++---- .../options/sources/dynamic/_index.en.md | 6 ++-- .../options/sources/dynamic/_index.nb.md | 2 +- .../sources/from-data-model/_index.en.md | 14 ++++---- .../sources/from-data-model/_index.nb.md | 16 ++++----- .../options/sources/shared/_index.en.md | 4 +-- .../options/sources/shared/_index.nb.md | 4 +-- .../options/sources/static/_index.en.md | 27 +++++++++------ .../options/sources/static/_index.nb.md | 34 +++++++++++-------- 10 files changed, 72 insertions(+), 59 deletions(-) diff --git a/content/altinn-studio/guides/development/options/sources/_index.en.md b/content/altinn-studio/guides/development/options/sources/_index.en.md index 8b8b8349fc..33effd517b 100644 --- a/content/altinn-studio/guides/development/options/sources/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/_index.en.md @@ -7,11 +7,11 @@ weight: 10 When you set up an options-enabled component in Altinn Studio, it needs to be connected to a source of options. There are three different properties in the component configuration that can be used for this, depending on the use case: -| Property | Usage | -|-------------|-----------------------------------------------------------------------------------------------------------------------------------| -| `options` | [Static options defined per-component](./static/#in-component-configuration) | -| `optionsId` | Either [static options from on json files](./static/#from-json-files), [dynamic options](./dynamic) or [shared options](./shared) | -| `source` | [Options from the data model](./from-data-model) | +| Property | Usage | +|-------------|----------------------------------------------------------------------------------------------------------------------------------| +| `options` | [Static options defined per-component](./static/#in-component-configuration) | +| `optionsId` | Either [code lists from json files](./static/#from-json-files), [dynamic code lists](./dynamic) or [shared code lists](./shared) | +| `source` | [Code lists from the data model](./from-data-model) | At least one such property has to be set in the component configuration. If multiple are set, the configuration precedence will be the opposite of the table above, so `source` will take precedence over `optionsId`, which will take precedence over `options`. diff --git a/content/altinn-studio/guides/development/options/sources/_index.nb.md b/content/altinn-studio/guides/development/options/sources/_index.nb.md index 92476c98f8..749aeb84e3 100644 --- a/content/altinn-studio/guides/development/options/sources/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/_index.nb.md @@ -4,13 +4,15 @@ description: De ulike kildene Altinn Studio kan bruke for svaralternativer weight: 10 --- -Når du setter opp en komponent i Altinn Studio som skal ha svaralternativer, må den kobles til en kilde for svaralternativer. Det er tre forskjellige egenskaper i komponentkonfigurasjonen som kan brukes til dette, avhengig av bruksområdet: +Når du setter opp en komponent i Altinn Studio som skal ha svaralternativer, må den kobles til en kilde for +svaralternativer. Det er tre forskjellige egenskaper i komponentkonfigurasjonen som kan brukes til dette, +avhengig av bruksområdet: -| Egenskap | Bruksområde | -|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `options` | [Statiske svaralternativer definert per komponent](./static/#i-komponentkonfigurasjonen) | -| `optionsId` | Enten [statiske svaralternativer fra json-filer](./static/#fra-json-filer), [dynamiske svaralternativer](./dynamic) eller [delte svaralternativer](./shared) | -| `source` | [Svaralternativer fra datamodellen](./from-data-model) | +| Egenskap | Bruksområde | +|-------------|--------------------------------------------------------------------------------------------------------------------------------------------| +| `options` | [Statiske svaralternativer definert per komponent](./static/#i-komponentkonfigurasjonen) | +| `optionsId` | Enten [statiske kodelister fra json-filer](./static/#fra-json-filer), [dynamiske kodelister](./dynamic) eller [delte kodelister](./shared) | +| `source` | [Kodelister fra datamodellen](./from-data-model) | Minst en slik egenskap må settes i komponentkonfigurasjonen. Hvis flere er satt, vil konfigurasjonsprioriteten være motsatt av tabellen ovenfor, slik at `source` vil ha forrang over `optionsId`, som vil ha forrang over `options`. diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md index 8c7856917c..de72037596 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.en.md @@ -1,5 +1,5 @@ --- -title: Dynamic options +title: Dynamic code lists linktitle: Dynamic description: Generated runtime by custom C# code toc: false @@ -14,7 +14,7 @@ For public code lists, implement the `IAppOptionsProvider` interface, while for ### Public code lists -Below you find an example of how to implement a public options provider. +Below you find an example of how to implement a public code list provider. ```C# using Altinn.App.Common.Models; @@ -75,7 +75,7 @@ The result of this implementation will be available at the endpoint `{org}/{app} } ``` -### Secured options +### Secured code lists If you want to produce lists of options that are sensitive you can implement `IInstanceAppOptionsProvider`, which will validate that the user has read rights as defined in the authorization policy from the `policy.xml`-file. Below you'll find an example of how to implement a secured options provider. diff --git a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md index cb0a919b45..dcb9da9ad7 100644 --- a/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/dynamic/_index.nb.md @@ -1,5 +1,5 @@ --- -title: Dynamiske svaralternativer +title: Dynamiske kodelister linktitle: Dynamisk description: Generert ved kjøring fra C#-kode toc: false diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md index 4a0f480632..6e816ee16c 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.en.md @@ -1,21 +1,21 @@ --- -title: Options from repeating structures +title: Code list from repeating structures linktitle: From data model -description: Options made from a repeating structure in the data model +description: Code list made from a repeating structure in the data model weight: 150 aliases: - /altinn-studio/guides/development/options/repeating-group-codelists --- -In the previous section about [dynamic options](../dynamic) we covered how to write code on the backend to generate dynamic options for a component. You could use pass certain values from the data model to the backend to generate those options (via [query parameters](../dynamic#query-parameters)), but that approach scales poorly when the query parameters would end up changing the options frequently, i.e. when the options are functionally unique for some set of data in the data model. +In the previous section about [dynamic code lists](../dynamic) we covered how to write code on the backend to generate a dynamic code list for a component. You could use pass certain values from the data model to the backend to generate that code list (via [query parameters](../dynamic#query-parameters)), but that approach scales poorly when the query parameters would end up changing the code list frequently, i.e. when the options are functionally unique for some set of data in the data model. -Another approach is to set up options based on a 'repeating group' in the data model. Such a repeating object in the data model could also represent a list of options for a dropdown, radio buttons, or checkboxes. This is especially useful combined with the [RepeatingGroup](../../../../../reference/ux/fields/grouping/repeating) component, as it allows the user to add and remove items from the list, and the options will automatically update. +Another approach is to set up a code list based on a 'repeating group' in the data model. Such a repeating object in the data model could also represent a list of options for a dropdown, radio buttons, or checkboxes. This is especially useful combined with the [RepeatingGroup](../../../../../reference/ux/fields/grouping/repeating) component, as it allows the user to add and remove items from the list, and the code list will automatically update. This functionality does not require the use of any `RepeatingGroup` component in the form layout, but it does require that the data model contains a repeating structure. ### Configuration -To set up options derived from the data model, use the `source` property in your component configuration. +To set up a code list derived from the data model, use the `source` property in your component configuration. This property contains the fields `group`, `label`, and `value`. Example: ```json {hl_lines=["5-9"]} @@ -33,11 +33,11 @@ This property contains the fields `group`, `label`, and `value`. Example: Explanation: -- **group** - the repeating group field in the data model to base the options on +- **group** - the repeating group field in the data model to base the code list on - **label** - a reference to a text id to be used as the label for each option, see more below. - **value** - a reference to a field in the group that should be used as the option value. Notice that we set up a placeholder `[{0}]` that will be replaced with the index of the repeating element. -The **value** field must be unique for each element. If the repeating group does not contain a field which is unique for each item it is recommended to add a field to the data model that can be used as identifier, for instance a GUID. Non-unique values will be filtered out from all option lists, so not choosing a unique value can make it seem like the options are not being correctly populated. +The **value** field must be unique for each element. If the repeating group does not contain a field which is unique for each item it is recommended to add a field to the data model that can be used as identifier, for instance a GUID. Non-unique values will be filtered out from all code lists, so not choosing a unique value can make it seem like the code list is not being correctly populated. As for the **label** property, you have to define a text resource that can be used as a label for each option. In the example below, other values from the repeating structure is used in the label via [variables in text](/altinn-studio/reference/ux/texts): diff --git a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md index d25de60ecd..307d097311 100644 --- a/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/from-data-model/_index.nb.md @@ -1,21 +1,21 @@ --- -title: Svaralternativer fra repeterede strukturer +title: Kodelister fra repeterede strukturer linktitle: Fra datamodellen -description: Svaralternativer hentet fra en repeterende struktur i datamodellen +description: Kodelister hentet fra en repeterende struktur i datamodellen weight: 150 aliases: - /nb/altinn-studio/guides/development/options/repeating-group-codelists --- -I den forrige seksjonen om [dynamiske svaralternativer](../dynamic) beskrev vi hvordan man kan skrive kode på backend for å generere dynamiske svaralternativer for en komponent. Du kunne også sende visse verdier fra datamodellen til backend for å generere disse alternativene (via [spørringsparametre](../dynamic#spørringsparametre)). Denne fremgangsmåten skalerer dårlig når spørringsparametrene ender opp med å endre alternativene ofte, dvs. når alternativene er funksjonelt unike for en del av dataene i datamodellen. +I den forrige seksjonen om [dynamiske kodelister](../dynamic) beskrev vi hvordan man kan skrive kode på backend for å generere dynamiske kodelister. Du kunne også sende visse verdier fra datamodellen til backend for å generere denne kodelisten (via [spørringsparametre](../dynamic#spørringsparametre)). Denne fremgangsmåten skalerer dårlig når kodelisten ender opp med å endre alternativene ofte, dvs. når alternativene er funksjonelt unike for en del av dataene i datamodellen. -En annen tilnærming er å sette opp svaralternativer basert på en 'repeterende gruppe' i datamodellen. En slik repeterende struktur i datamodellen kan også representere en liste over alternativer for en nedtrekksliste, radioknapper eller avmerkingsbokser. Dette er spesielt nyttig i kombinasjon med [RepeatingGroup](../../../../../reference/ux/fields/grouping/repeating) komponenten, da det lar brukeren legge til og fjerne elementer fra listen, og alternativene vil automatisk oppdateres. +En annen tilnærming er å sette opp en kodeliste basert på en 'repeterende gruppe' i datamodellen. En slik repeterende struktur i datamodellen kan også representere en liste over alternativer for en nedtrekksliste, radioknapper eller avmerkingsbokser. Dette er spesielt nyttig i kombinasjon med [RepeatingGroup](../../../../../reference/ux/fields/grouping/repeating) komponenten, da det lar brukeren legge til og fjerne elementer fra listen, og alternativene vil automatisk oppdateres. Denne funksjonaliteten krever ikke bruk av noen `RepeatingGroup` komponent i skjemalayout, men det krever at datamodellen inneholder en repeterende struktur. ### Konfigurasjon -For å sette opp svaralternativer som hentes ut fra datamodellen brukes egenskapen `source`. +For å sette opp kodelister som hentes ut fra datamodellen brukes egenskapen `source`. I dette objektet definerer man feltene `group`, `label` og `value`. Eksempel: ```json {hl_lines=["5-9"]} @@ -33,12 +33,12 @@ I dette objektet definerer man feltene `group`, `label` og `value`. Eksempel: Forklaring: -- **group** - den repeterende strukturen i datamodellen man baserer svaralternativene på. -- **label** - en referanse til en tekstnøkkel som brukes som ledetekst for hvet svaralternativ. Se mer under. +- **group** - den repeterende strukturen i datamodellen man baserer kodelisten på. +- **label** - en referanse til en tekstnøkkel som brukes som ledetekst for hvert svaralternativ. Se mer under. - **value** - en referanse til det feltet i den repeterende strukturen som skal bruke som verdi, og dermed lagres når brukeren gjør et valg. Legg merke til at vi har fyllt inn `[{0}]` som vil bli erstattet med indeksen til det repeterende elementet. -Verdien hentet ut fra **value** må være unikt for hvert repeterende element. Om man ikke har et felt som er unikt per rad, anbefales det å legge på et ekstra felt i datamodellen som kan benyttes som identifikator f.eks en GUID eller liknende. Dersom verdien ikke er unik vil den bli filtrert bort fra alle svaralternativlister, og antallet svaralternativer tilgjengelige for brukeren kan da være noe lavere enn forventet ut fra datamodellen. +Verdien hentet ut fra **value** må være unikt for hvert repeterende element. Om man ikke har et felt som er unikt per rad, anbefales det å legge på et ekstra felt i datamodellen som kan benyttes som identifikator f.eks en GUID eller liknende. Dersom verdien ikke er unik vil den bli filtrert bort fra alle kodelister, og antallet svaralternativer tilgjengelige for brukeren kan da være noen færre enn forventet ut fra det som ligger i datamodellen. For **label** feltet må vi definere en tekstressurs som kan bli brukt som ledetekst for hvert svaralternativ. I eksempelet under, brukes andre verdier fra den repeterende strukturen i ledeteksten via [variabler i tekst](/nb/altinn-studio/reference/ux/texts): diff --git a/content/altinn-studio/guides/development/options/sources/shared/_index.en.md b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md index 28f9bff468..27975c2186 100644 --- a/content/altinn-studio/guides/development/options/sources/shared/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.en.md @@ -1,7 +1,7 @@ --- -title: Common shared options +title: Common shared code lists linktitle: Shared -description: Options that are shared across applications +description: Code lists that are shared across applications toc: false weight: 200 aliases: diff --git a/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md index 29faa34945..45c57c8582 100644 --- a/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/shared/_index.nb.md @@ -1,6 +1,6 @@ --- -title: Delte standard kodelister -linktitle: Delte +title: Felles standard kodelister +linktitle: Felles description: Delte standard kodelister som kan brukes i flere applikasjoner toc: false weight: 200 diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.en.md b/content/altinn-studio/guides/development/options/sources/static/_index.en.md index d9ea6041d4..2462e4230e 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.en.md @@ -8,18 +8,20 @@ aliases: - /altinn-studio/guides/development/options/static-codelists --- -For simpler use-cases, a static code list is easy to configure. These can either be set directly in the component -configuration or in a json file in the application repository. Which method to use depends on the re-usability of -the code list. If multiple components should use the same code list, it is recommended to use the [json file method](#from-json-files). +For simpler use-cases, a static list of options or a simple code list is easy to configure. +These can either be set directly in the component configuration (in which case we call them options) or in a json file +in the application repository (the simplest form for code lists). Which method to use depends on the need for reusability. +If multiple components need to use the same set of options, it is recommended to +use the [json file method](#from-json-files) and thus turn it into a code list. -Note that even though a static code list can be completely static, it is also possible to make it (a bit more) dynamic +Note that even though a static list of options can be completely static, it is also possible to make it (a bit more) dynamic by [filtering the options](../../functionality/filtering) using expressions. If you want even more flexibility, you can also [create your own code-based code list](../dynamic). -## In component configuration +## In component configuration (options) -In the example configuration, a Dropdown component is set up with a static code list. The `options` property is an -array of objects, where each object represents a code list item. The `value` property is the value that will be +In the example configuration, a Dropdown component is set up with a simple set of options. The `options` property is an +array of objects, where each object represents a choice for the user. The `value` property is the value that will be saved in the data model when the user selects the item. The `label` property is the text that will be displayed to the user. @@ -48,11 +50,16 @@ the user. } ``` -## From JSON files +## From JSON files (code list) -By adding json based option files in the application repository, the application will automatically read the file and expose it through the options api. For this to work, the files must be placed in the `App/options/` folder and be named according to the following conventions `{optionId}.json` for the application to recognize them. +By adding json based option files in the application repository, the application will automatically read the file +and expose it through the options api. For this to work, the files must be placed in the `App/options/` folder and be +named according to the following conventions `{optionId}.json` for the application to recognize them. -For example if you have a list of countries in a file named `countries.json`, the optionId would be `countries`, and would be exposed through the api at `{org}/{app}/api/options/countries`. The static code lists should be in a special format as shown below: +For example if you have a list of countries in a file named `countries.json`, the optionId would be `countries`, and +would be exposed through the api at `{org}/{app}/api/options/countries`. + +The static code lists should be in the format as shown below: ```json [ diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md index bf8375fc79..f67c5a4f9c 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md @@ -1,5 +1,5 @@ --- -title: Statiske svaralternativer +title: Statiske svaralternativer og enkle kodelister linktitle: Statisk description: Svaralternativer som ikke endrer seg, men som kan filtreres toc: false @@ -8,20 +8,21 @@ aliases: - /nb/altinn-studio/guides/development/options/static-codelists --- -For enklere brukstilfeller er statiske kodelister det letteste å sette opp. Disse kan enten settes direkte -i komponentkonfigurasjonen eller i en json-fil i app-repositoriet. Hvilken metode som bør brukes avhenger av -gjenbruksbehovet til kodelisten. Hvis flere komponenter skal bruke samme kodeliste, anbefales det å -[putte kodelisten i en json-fil](#fra-json-filer). +For enklere brukstilfeller er statiske svaralternativer og kodelister det letteste å sette opp. Disse kan enten settes direkte +i komponentkonfigurasjonen (dette kaller vi ofte svaralternativer) eller i en json-fil i +app-repositoriet (den enkleste formen for kodeliste). Hvilken metode som bør brukes avhenger av +gjenbruksbehovet. Hvis flere komponenter skal bruke de samme svaralternativene, anbefales det å +[putte kodelisten i en json-fil](#fra-json-filer) og dermed gjøre den om til en kodeliste. -Legg merke til at selv om en slik kodeliste kan være helt statisk, er det også mulig å gjøre den (litt mer) dynamisk -ved å [filtrere svaralternativene](../../functionality/filtering) ved hjelp av e uttrykk. Ønsker du enda mer +Legg merke til at selv om slike svaralternativer kan være helt statisk, er det også mulig å gjøre dem (litt mer) dynamiske +ved å [filtrere svaralternativene](../../functionality/filtering) ved hjelp av et uttrykk. Ønsker du enda mer fleksiilitet, kan du også [lage en egen kodebasert kodeliste](../dynamic). -## I komponentkonfigurasjonen +## I komponentkonfigurasjonen (svaralternativer) -I denne eksempelkonfigurasjonen er en Dropdown-komponent satt opp med en statisk kodeliste. Egenskapen `options` er en -array av objekter, hvor hvert objekt representerer et kodelisteelement. Egenskapen `value` er verdien som vil bli -lagret i datamodellen når brukeren velger elementet. Egenskapen `label` er teksten som vil bli vist til brukeren. +I denne eksempelkonfigurasjonen er en Dropdown-komponent satt opp med en statiske svaralternativer. Egenskapen `options` er en +liste med objekter, hvor hvert objekt representerer et svaralternativ. Egenskapen `value` er verdien som vil bli +lagret i datamodellen når brukeren velger elementet. Egenskapen `label` er ledeteksten som vil bli vist til brukeren. ```json {hl_lines=["8-21"]} { @@ -48,11 +49,14 @@ lagret i datamodellen når brukeren velger elementet. Egenskapen `label` er teks } ``` -## Fra JSON-filer +## Fra JSON-filer (kodeliste) -Ved å legge json-lister i options mappen i app repo vil appen automatisk lese denne filen og eksponere det gjennom options-apiet. -Options filene må ligge under `App/options/` og vil bli differensiert ved hjelp av navngivningen på json-filen. F.eks `land.json`. Her vil da optionsId være `land`, og vil være eksponert gjennom endepunktet `{org}/{app}/api/options/land`. -Kodelistene må være på et spesifikt format. Eksempel på en kodeliste som inneholder land (`App/options/land.json`): +Ved å legge json-lister i `options`-mappen i app repo vil appen automatisk lese denne filen og eksponere det gjennom `options`-APIet. +Options filene må ligge under `App/options/`. Lager man f.eks `land.json`, kan man sette opp en komponent med egenskapen `"optionsId": "land"`. +Kodelisten kan hentes fra API via endepunktet `{org}/{app}/api/options/land`. + + +Kodelistene må følge et spesifikt format. Eksempel på en kodeliste som inneholder land (`App/options/land.json`): ```json [ From f5676f10726dc1b6cf763049f44b01c84bde8bcc Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Mon, 16 Dec 2024 16:45:54 +0100 Subject: [PATCH 30/31] Adding optionFilter to the table of where we support expressions (duh! it's what I made all these changes for!) --- content/altinn-studio/reference/logic/expressions/_index.en.md | 1 + content/altinn-studio/reference/logic/expressions/_index.nb.md | 1 + 2 files changed, 2 insertions(+) diff --git a/content/altinn-studio/reference/logic/expressions/_index.en.md b/content/altinn-studio/reference/logic/expressions/_index.en.md index c620df63ae..89c1d45cd8 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.en.md +++ b/content/altinn-studio/reference/logic/expressions/_index.en.md @@ -162,6 +162,7 @@ Dynamic expressions are currently available for use in these properties, as defi | [Option based components](../../../guides/development/options/sources/from-data-model/#expression-support) | `source.description` | [String](#strings) | ✅ | ❌ | | [Option based components](../../../guides/development/options/sources/from-data-model/#expression-support) | `source.helpText` | [String](#strings) | ✅ | ❌ | | [Option based components](../../../guides/development/options/sources/dynamic/#based-on-expressions) | `queryParameters.[*]` | [String](#strings) | ✅ | ❌ | +| [Option based components](../../../guides/development/options/functionality/filtering) | `optionFilter` | [String](#strings) | ✅ | ❌ | | All | `textResourceBindings.[*]` \* | [String](#strings) | ✅ | ❌ | \* = The values that can be overridden with textResourceBindings vary from component to component, but will work wherever diff --git a/content/altinn-studio/reference/logic/expressions/_index.nb.md b/content/altinn-studio/reference/logic/expressions/_index.nb.md index 7fe66286e6..720d89fab5 100644 --- a/content/altinn-studio/reference/logic/expressions/_index.nb.md +++ b/content/altinn-studio/reference/logic/expressions/_index.nb.md @@ -157,6 +157,7 @@ Dynamiske uttrykk er foreløpig tilgjengelig for bruk i disse egenskapene, som d | [Kodelistebaserte komponenter](../../../guides/development/options/sources/from-data-model/#støtte-for-uttrykk) | `source.description` | [Streng](#strenger) | ✅ | ❌ | | [Kodelistebaserte komponenter](../../../guides/development/options/sources/from-data-model/#støtte-for-uttrykk) | `source.helpText` | [Streng](#strenger) | ✅ | ❌ | | [Kodelistebaserte komponenter](../../../guides/development/options/sources/dynamic/#basert-på-uttrykk) | `queryParameters.[*]` | [Streng](#strenger) | ✅ | ❌ | +| [Kodelistebaserte komponenter](../../../guides/development/options/functionality/filtering) | `optionFilter` | [Streng](#strenger) | ✅ | ❌ | | Alle | `textResourceBindings.[*]` \* | [Streng](#strenger) | ✅ | ❌ | \* = Hvilke verdier man kan overstyre med textResourceBindings varierer fra komponent til komponent, men vil fungere på From 2632ea56439e1ec787e1f636deb720c3f95ec9c3 Mon Sep 17 00:00:00 2001 From: Ole Martin Handeland Date: Mon, 16 Dec 2024 16:51:14 +0100 Subject: [PATCH 31/31] Fixing broken links --- .../guides/development/options/sources/_index.en.md | 10 +++++----- .../guides/development/options/sources/_index.nb.md | 10 +++++----- .../development/options/sources/static/_index.en.md | 2 +- .../development/options/sources/static/_index.nb.md | 2 +- .../components/_common-props-content/optionsId.en.md | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/content/altinn-studio/guides/development/options/sources/_index.en.md b/content/altinn-studio/guides/development/options/sources/_index.en.md index 33effd517b..65207e566c 100644 --- a/content/altinn-studio/guides/development/options/sources/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/_index.en.md @@ -7,11 +7,11 @@ weight: 10 When you set up an options-enabled component in Altinn Studio, it needs to be connected to a source of options. There are three different properties in the component configuration that can be used for this, depending on the use case: -| Property | Usage | -|-------------|----------------------------------------------------------------------------------------------------------------------------------| -| `options` | [Static options defined per-component](./static/#in-component-configuration) | -| `optionsId` | Either [code lists from json files](./static/#from-json-files), [dynamic code lists](./dynamic) or [shared code lists](./shared) | -| `source` | [Code lists from the data model](./from-data-model) | +| Property | Usage | +|-------------|--------------------------------------------------------------------------------------------------------------------------------------------| +| `options` | [Static options defined per-component](./static/#in-component-configuration-options) | +| `optionsId` | Either [code lists from json files](./static/#from-json-files-code-list), [dynamic code lists](./dynamic) or [shared code lists](./shared) | +| `source` | [Code lists from the data model](./from-data-model) | At least one such property has to be set in the component configuration. If multiple are set, the configuration precedence will be the opposite of the table above, so `source` will take precedence over `optionsId`, which will take precedence over `options`. diff --git a/content/altinn-studio/guides/development/options/sources/_index.nb.md b/content/altinn-studio/guides/development/options/sources/_index.nb.md index 749aeb84e3..c6dc1351db 100644 --- a/content/altinn-studio/guides/development/options/sources/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/_index.nb.md @@ -8,11 +8,11 @@ Når du setter opp en komponent i Altinn Studio som skal ha svaralternativer, m svaralternativer. Det er tre forskjellige egenskaper i komponentkonfigurasjonen som kan brukes til dette, avhengig av bruksområdet: -| Egenskap | Bruksområde | -|-------------|--------------------------------------------------------------------------------------------------------------------------------------------| -| `options` | [Statiske svaralternativer definert per komponent](./static/#i-komponentkonfigurasjonen) | -| `optionsId` | Enten [statiske kodelister fra json-filer](./static/#fra-json-filer), [dynamiske kodelister](./dynamic) eller [delte kodelister](./shared) | -| `source` | [Kodelister fra datamodellen](./from-data-model) | +| Egenskap | Bruksområde | +|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------| +| `options` | [Statiske svaralternativer definert per komponent](./static/#i-komponentkonfigurasjonen-svaralternativer) | +| `optionsId` | Enten [statiske kodelister fra json-filer](./static/#fra-json-filer-kodeliste), [dynamiske kodelister](./dynamic) eller [delte kodelister](./shared) | +| `source` | [Kodelister fra datamodellen](./from-data-model) | Minst en slik egenskap må settes i komponentkonfigurasjonen. Hvis flere er satt, vil konfigurasjonsprioriteten være motsatt av tabellen ovenfor, slik at `source` vil ha forrang over `optionsId`, som vil ha forrang over `options`. diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.en.md b/content/altinn-studio/guides/development/options/sources/static/_index.en.md index 2462e4230e..04a4ea0aff 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.en.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.en.md @@ -12,7 +12,7 @@ For simpler use-cases, a static list of options or a simple code list is easy to These can either be set directly in the component configuration (in which case we call them options) or in a json file in the application repository (the simplest form for code lists). Which method to use depends on the need for reusability. If multiple components need to use the same set of options, it is recommended to -use the [json file method](#from-json-files) and thus turn it into a code list. +use the [json file method](#from-json-files-code-list) and thus turn it into a code list. Note that even though a static list of options can be completely static, it is also possible to make it (a bit more) dynamic by [filtering the options](../../functionality/filtering) using expressions. If you want even more flexibility, diff --git a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md index f67c5a4f9c..697d2961c1 100644 --- a/content/altinn-studio/guides/development/options/sources/static/_index.nb.md +++ b/content/altinn-studio/guides/development/options/sources/static/_index.nb.md @@ -12,7 +12,7 @@ For enklere brukstilfeller er statiske svaralternativer og kodelister det lettes i komponentkonfigurasjonen (dette kaller vi ofte svaralternativer) eller i en json-fil i app-repositoriet (den enkleste formen for kodeliste). Hvilken metode som bør brukes avhenger av gjenbruksbehovet. Hvis flere komponenter skal bruke de samme svaralternativene, anbefales det å -[putte kodelisten i en json-fil](#fra-json-filer) og dermed gjøre den om til en kodeliste. +[putte kodelisten i en json-fil](#fra-json-filer-kodeliste) og dermed gjøre den om til en kodeliste. Legg merke til at selv om slike svaralternativer kan være helt statisk, er det også mulig å gjøre dem (litt mer) dynamiske ved å [filtrere svaralternativene](../../functionality/filtering) ved hjelp av et uttrykk. Ønsker du enda mer diff --git a/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md b/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md index 24933ddd91..247c7220ee 100644 --- a/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md +++ b/content/altinn-studio/reference/ux/components/_common-props-content/optionsId.en.md @@ -19,7 +19,7 @@ To add options from a code list, select "Kodeliste" and enter a code list ID.
-If you wish to [secure dynamic code lists](/altinn-studio/guides/development/options/sources/dynamic/#secured-options), you can check this option: +If you wish to [secure dynamic code lists](/altinn-studio/guides/development/options/sources/dynamic/#secured-code-lists), you can check this option: {{% image file="component-settings/secure.png" %}}