⚠️ Dynamikk er et område under aktiv utvikling. Denne funksjonaliteten er for øyeblikket tilgjengelig som en betaversjon
i Altinn Studio og tilbyr begrensede konfigurasjonsalternativer. Grensesnittet tillater bare å bygge uttrykk med ett
nivå av nøsting, noe som betyr at et ubegrenset antall ikke-nøstede uttrykk kan kombineres ved å bruke enten ELLER
eller OG-operatoren. Imidlertid tillater verktøyet å redigere mer kompliserte uttrykk ved å skrive fritt. For
øyeblikket er verktøyet også begrenset til å koble uttrykk til boolske komponentfelt.
Les Uttrykk i Altinn Studio om hvordan uttrykk lages i
Altinn Studio.
Introduksjon
Dynamikk via uttrykk gjør det mulig å definere enkel dynamisk oppførsel i en Altinn 3 app, som for eksempel ved å
definere om et skjemafelt skal vises eller skjules, om feltet skal være påkrevd eller skrivebeskyttet.
Uttrykkene er tilgjengelige i alle Altinn 3-apper som bruker frontend-versjon
3.54.0 eller nyere. Bruker man denne versjonen
(eller siste hovedversjon) har man mulighet til å benytte dynamiske uttrykk til flere bruksområder.
Fra versjon 7.2.0 av nuget-pakkene er også uttrykkene støttet i backend.
Det gjør at serveren vil kunne evaluere uttrykkene og fjerne data ved innsending som potensielt er lagret
i datamodellen og er knyttet til felter/komponenter som i ettertid er skjult.
Merk at dette bare gjelder data i datamodellen som er knyttet til skjulte komponenter - data i datamodellen som ikke
er knyttet til komponenter (og dermed implisitt skjult for brukeren) vil ikke fjernes automatisk.
Det gjør det også mulig å unnlate å sende inn data som ellers er tilknyttet påkrevde felter - dersom disse påkrevde
feltene er skjult i skjemaet ved hjelp av dynamiske uttrykk. Dette gjelder også ved innsending direkte fra API.
NB: Automatisk fjerning av skjult data må foreløpig aktiveres manuelt (opt-in) ved at man legger til følgende
linje i App/appsettings.json etter at man har oppgradert nuget-pakkene
til 7.2.0 eller nyere:
Uttrykkene er bygget opp som et slags mini-programmeringsspråk, hvor alt er definert i JSON. Selve uttrykkene er alltid
en liste (array) med verdier, hvor den første verdien i hver liste alltid er et funksjonsnavn. Resten
av verdiene sendes som inndata/argumenter til funksjonen.
["equals", "foo", "bar"]
I eksempelet over blir strengene “foo” og “bar” sammenlignet. De er ulike, så resultatet av dette uttrykket blir en
boolsk verdi; false.
Denne funksjonen, equals, forventer å få inn to strenger som inndata/argumenter. Det
er også mulig å gi den andre uttrykk. Gjør man dette vil uttrykket bli tolket slik at de innerste funksjonene blir kjørt
først, og de ytterste kjørt sist.
["equals", ["component", "firstName"], "John"]
I dette eksempelet blir det innerste uttrykket/funksjonskallet ["component", "firstName"] kjørt først. Om verdien til
komponenten “firstName” er lik strengen “John”, gir funksjonen resultatet den boolske verdien “true”.
Dersom man da bruker dette uttrykket for hidden-egenskapen til en komponent, vil komponenten bli skjult dersom man
skriver inn “John” i “firstName”-komponenten et annet sted i applikasjonen:
Det er ingen begrensninger rundt hvor store/dype uttrykkene kan være. Som en øvelse, se om du klarer å lese hva dette
uttrykket gjør, og hvilke mulige verdier det kan returnere:
[
"if",
["greaterThanEq", ["component", "age"], 16],
[
"if",
["lessThan", ["component", "age"], 62],
"Please consider applying for our open position!",
"else",
["concat", "At ", ["component", "age"], ", you are eligible for retirement"]
],
"else",
["concat", "At ", ["component", "age"], ", you should stay in (pre)school"]
]
* = 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
du mer informasjon om her
Her endrer vi teksten til redigeringsknappen i en repeterende gruppe basert på om IsPrefill er satt til true i
en gitt adresse i datamodellen. Dersom IsPrefill er true for en adresse, vil raden som viser frem den adressen ha en
redigerings-knapp med teksten "View". Hvis IsPrefill er false blir teksten på knappen til den spesifikke raden
"Edit".
Det er verdt å merke seg at dersom et oppslag på IsPrefill gir resultatet null(ikke funnet) så konverteres
resultatet til false når det blir brukt i en if. Les mer detaljert om dette i seksjonene if og datatyper
Når man skal skrive et uttrykk er det greit å vite noenlunde hva resultatet kommer til å bli, og om uttrykket er gyldig.
Ugyldige uttrykk gir en advarsel i JavaScript-konsollet i nettleseren når siden lastes, så det kan være lurt å ha
dette konsollet åpent når man utvikler en applikasjon og tester uttrykkene lokalt.
Det er også mulig å teste ut kjøring av et uttrykk rett i utviklerverktøyene. Det gjøres ved å trykke Ctrl + Shift + K
(eller Cmd + Shift + K på Mac) og navigere til fanen for uttrykk. Uttrykk vil kunne oppføre seg annerledes alt etter
hvilken komponent de evalueres i nærheten av. Derfor kan man også velge en komponent som skal brukes som kontekst når
uttrykket evalueres i utviklerverktøyene.
NB: Her beskrives noen implementasjonsdetaljer i app-frontend-react,
og er kun relevant når du skal prøve et uttrykk i utviklerverktøyene som er avhengig av en kjent posisjon i en
repeterende gruppe. Dette kan endres i fremtiden, og slike endringer vil ikke påvirke uttrykk som man har definert i en
applikasjon. Der hentes konteksten ut fra hvor uttrykket er definert i layout-filen.
Se for deg en repeterende gruppe for personer med to felt; navn og alder.
Gitt dette uttrykket:
["component", "alder"]
Hva vil alderen være? Det vil kunne variere etter hvilken gruppe som evaluerer
uttrykket. Har man har to grupper/rader vil både navn- og alder-komponentene finnes to ganger hver. Disse vil få
ID-ene navn-0 og alder-0 (for den første raden) og navn-1 og alder-1 (for den andre raden).
Tenk deg at følgende data er fyllt inn i en repeterende gruppe:
Navn
Komponent-ID
Alder
Komponent-ID
Per
navn-0
24
alder-0
Kari
navn-1
36
alder-1
Ola
navn-2
18
alder-2
Gitt følgende uttrykk:
["component", "alder"]
Og med disse forutsetningene:
Man har ikke gitt noen kontekst (eventuelt, uttrykket plasseres på en komponent som ikke er i nærheten av
en alder-komponent)
Man evaluerer uttrykket i kontekst av navn-0
Man evaluerer uttrykket i kontekst av navn-1
Hva vil resultatet bli i de forskjellige eksemplene? Her er svarene:
Denne vil finne “første og beste” alder-komponent, og finner dermed alder-0. Den returnerer
derfor 24, Per sin alder.
Her prøver vi å lete i kontekst av navn-komponenten på første rad, og igjen finner vi 24, Per sin alder.
siste eksempel har vi spesifisert andre rad i den repeterende gruppen ved å evaluere i kontekst av navn-1.
Her finner vi den nærmeste alder-komponenten alder-1, som er 36, Kari sin alder.
Funksjoner
Disse funksjonene er tilgjengelige for bruk i uttrykk:
Disse to funksjonene sammenligner to strenger for å sjekke om de er like (equals) eller ulike (notEquals). Om
du sender inn andre verdier enn strenger, blir verdiene konvertert og sammenlignet som strenger
(les mer om konvertering her).
Denne funksjonen tar inn en boolsk verdi eller noe som kan konverteres til en boolsk verdi, og
returnerer den motsatte boolske verdien. Sann blir til usann, usann blir til sann.
Funksjonen kan være nyttig om du ønsker å snu et uttrykk. Istedenfor å tenke at du skal skrive et uttrykk som
skjuler en komponent gitt noen forutsetninger, kan du pakke uttrykket inn i not og skrive uttrykket ut fra
hva som skal til for å vise komponenten:
Disse 4 funksjonene forventer to tall inn, og sammenligner om det første med det andre. Det vil si, for funksjonen
greaterThan er uttrykket sant dersom det første tallet er større enn det andre.
Funksjon
Beskrivelse
Symbol
greaterThan
Er det første tallet større enn det andre tallet?
>
greaterThanEq
Er det første tallet større enn eller lik det andre tallet?
≥
lessThan
Er det første tallet mindre enn det andre tallet?
<
lessThanEq
Er det første tallet mindre enn eller lik det andre tallet?
≤
Dersom noen av argumentene til disse funksjonene er null blir resultatet false (uavhengig av om det er det
første eller andre argumentet).
Eksempel som sjekker om alder er over (eller lik) 18:
Denne funksjonen tar inn 0 eller flere strenger som argumenter, og returnerer en streng hvor alle strengene i
argumentene er slått sammen. Kalles funksjonen uten noen argumenter gis det en tom streng.
Legg merke til at funksjonen ikke automatisk legger til mellomrom eller komma når den slår sammen strenger. For å gi
et mer lesbart resultat anbefales det å legge inn bindetegn hvor nødvendig:
["concat", "Gratulerer med ", ["component", "alder"], "-årsdagen!"]
Uttrykket over gir teksten Gratulerer med 18-årsdagen! dersom verdien i alder-komponenten var 18.
I concat-funksjonen tolkes null-verdier som tomme strenger. Boolske verdier skrives
ut som strengene "true" og "false".
Funksjonene and og or forventer 1 eller flere boolske verdier, og gir et resultat ut fra om henholdsvis alle eller
minst en av verdiene var sanne (true).
if-funksjonen kan brukes for å forgrene et uttrykk slik at returverdien styres av resultatet av et annet
boolsk uttrykk. Funksjonen kan kalles på to forskjellige måter; med 2 eller 4 argumenter:
I alternativ 1 vil returverdien til funksjonen bli verdien gitt som andre argument dersom første argument er sant
(true). Om ikke returneres verdien null.
I alternativ 2 vil returverdien til funksjonen bli verdien gitt som andre argument dersom første argument er sant
(true). Om ikke returneres verdien gitt i fjerde argument. Man må alltid gi strengen "else" som tredje argument
om man vil kalle funksjonen med 4 argumenter. Det tredje argumentet er bare til for å gjøre uttrykket mer lesbart, og
har ingen funksjon ellers.
Om man ønsker flere betingelser og mulige returverdier kan man nøste flere kall til if inne i andre eller fjerde
argument:
[
"if",
["greaterThan", ["component", "birthYear"], 1945],
"Du ble født etter verdenskrigene",
"else",
[
"if",
["greaterThanEq", ["component", "birthYear"], 1939],
"Du ble født under andre verdenskrig",
"else",
"Du ble født før andre verdenskrig" ]
]
Om gjeldende språk er ukjent, vil nb returneres, som er standardspråket for Altinn 3-apper. Dermed kan man være trygg
på at denne funksjonen alltid returnerer et gyldig språk.
Bemerk: Denne funksjonen er ikke tigjengelig i backend-kode enda, og vil derfor gi en feilmelding dersom den blir
brukt noen steder hvor uttrykk kjøres på backend, og om man har slått på funksjonaliteten for å
automatisk slette skjulte data (RemoveHiddenDataPreview).
Funksjonen startsWith sjekker om strengen gitt som første argument starter med strengen gitt i andre argument, og
på samme vis vil funksjonen endsWith sjekke om første streng slutter med den andre strengen.
Noen detaljer som er verdt å nevne om disse funksjonene:
Alle funksjoner starter og slutter med en tom streng, så startsWith og endsWith vil alltid returnere true
dersom man bruker et uttrykk ["startsWith", "...", ""]. Dette er viktig å passe på om man bruker verdien til
en komponent eller et oppslag i datamodellen som andre argument.
Ingen strenger starter eller slutter med en null-verdi. Bruker man et uttrykk som dette:
vil alltid resultatet bli
false så lenge fornavnet ikke er gitt. Men som nevnt over, dersom fornavnet er satt til en tom streng (for eksempel
dersom brukeren har visket ut fornavnet sitt), vil uttrykket gi true dersom et fullt navn er satt. Dersom man vil
unngå noe av denne oppførselen kan man bruke if-funksjonen sammen med equals til å sjekke om noe er satt til
en tom streng.
Disse to funksjonene sjekker om streng A inkluderer eller ikke inkluderer streng B.
Både contains og notContains skiller mellom store og små bokstaver.
Det betyr at strengen “Hei” ikke inkluderer “hei”. Ønsker du å sammenligne uavhengig av store og små bokstaver kan du
bruke funksjonene lowerCase eller upperCase sammen med contains eller notContains.
Funksjonen commaContains tar imot to argumenter. Det første argumentet er en kommaseparert streng, og det andre
argumentet er strengen du ønsker å sjekke om er blant de kommaseparerte verdiene i første argument.
Legg merke til at eventuelle mellomrom før/etter komma, eller før/etter første verdi blir ignorert. Denne funksjonen
er spesielt nyttig i tilfeller hvor man bruker en komponent som lagrer flere verdier i en kommaseparert streng, som
Checkboxes og MultipleSelect.
Funksjonene lowerCase og upperCase tar imot en streng som input og returnerer en ny streng der alle tegnene er
konvertert til henholdsvis små eller store bokstaver.
["lowerCase", ["dataModel", "My.Model.LastName"]]
Disse funksjonene gir deg en enkel måte å konvertere mellom små og store bokstaver i en streng.
Et bruksområde kan være å kombinere en av disse funksjonene med andre sammenligningsfunksjoner slik at sammenligningene
gjøres uavhengig av om det ble brukt store eller små bokstaver i input-verdien.
Funksjonen round avrunder et tall til et heltall, eller valgfritt til et desimaltall med et konfigurerbart antall desimalpunkter.
Eksempel med avrunding med 2 desimalpunkter:
["round", "122.99843", "2"]
Eksempel med avrunding til nærmeste heltall:
["round", "3.4999"]
Returverdien fra denne funksjonen er en streng, slik at returverdien kan brukes for
fremvisning (merk at desimalskilletegnet alltid er punktum). Selv om returverdien er en streng kan denne også brukes
videre i uttrykk som forventer tall som inn-verdi.
Funksjonen text tar imot en nøkkel som argument og bruker denne nøkkelen til å hente ut den tilsvarende teksten fra en tekst-ressurs. Funksjonen returnerer verdien som er knyttet til den angitte nøkkelen.
Eksempel:
["text", "min-nøkkel-id"]
Bemerk: Husk å teste manuelt med tekstnøkler som inneholder variabler. Det er ikke sikkert disse vil fungere som
forventet.
Bemerk: Denne funksjonen er ikke tilgjengelig i backend-kode enda, og vil derfor gi en feilmelding dersom den blir
brukt noen steder hvor uttrykk kjøres på backend, og om man har slått på funksjonaliteten for å
automatisk slette skjulte data (RemoveHiddenDataPreview).
Funksjonen displayValue gjør et oppslag på en komponent og returnerer en formattert tekststreng som representerer verdien i datamodellen.
Dette er til forskjell fra component-funksjonen som returnerer rå-verdien som ligger i datamodellen.
Denne funksjonen egner seg best til visning av en komponent sin verdi for brukeren, og mindre til videre logikk basert på verdien som returneres.
Dette er spesielt relevant for Input-felter med tallformattering, datofelter, radioknapper (og andre komponenter med kodelister), osv.
Eksempel:
["displayValue", "component-id"]
Bemerk: Denne funksjonen er ikke tilgjengelig i backend-kode enda, og vil derfor gi en feilmelding dersom den blir
brukt noen steder hvor uttrykk kjøres på backend, og om man har slått på funksjonaliteten for å
automatisk slette skjulte data (RemoveHiddenDataPreview).
Denne funksjonen gjør det mulig å hente ut informasjon om gjeldende instans. Følgende nøkler kan brukes fom første
argument:
Nøkkel
Verdi
Eksempelverdi
instanceId
Gjeldende instans-ID
512345/48c31ffc-dcdd-416d-8bc7-194bec3b7bf0
instanceOwnerPartyId
Gjeldende aktør-ID
512345
instanceOwnerPartyType
Hva slags aktør eier instansen
"org", "person", "selfIdentified" eller "unknown"
appId
Den aktive appen sin ID
org/app-name
Alle disse oppslagene vil gi verdien null om man jobber i en tiltandsløs kontekst.
Om man gir andre nøkler enn de over, vil oppslaget resultere i en feilmelding. Denne oppførselen er unik blant
oppslagsfunksjonene, og gjøres for å sikre at man ikke prøver å hente informasjon som finnes i instansen men som ikke
(enda) er eksponert via en nøkkel her. Gi oss en tilbakemelding om du har ønsker om å hente ut
instansdata som ikke er tilgjengelig i denne funksjonen.
Oppslaget gjøres i samme datakilde som er tilgjengelig for språk/tekster.
Merk: Datakilden heter applicationSettings når brukt i språk/tekster, men verdiene må alltid lagres under
nøkkelen FrontEndSettings i appsettings.{miljø}.json). Av den grunn har funksjonen fått navnet frontendSettings
her, for å indikere at oppslag ikke kan gjøres i resten av appsettings.{miljø}.json.
Denne oppslagsfunksjonen gjør det mulig å hente verdier direkte fra gjeldende datamodell. Første og eneste argument
må peke et sted i datamodellen, og bruker det samme punktum-separerte formatet som brukt i dataModelBindings. Ved
bruk inne i repeterende grupper trenger man ikke bruke plassholdere for
indekser til gruppen - uttrykket finner selv den relative plasseringen i kontekst av en repeterende gruppe.
Legg merke til at oppslag bare fungerer mot datatyper som allerede er støttet i uttrykkene. Dersom man
slår opp et objekt eller en liste/array i datamodellen med dataModel-funksjonen får man alltid resultatet null.
Denne funksjonaliteten kan endres, da det er planlagt støtte for objekter og lister i uttrykkene i fremtiden.
Det første oppslaget (for å styre hidden på komponenten ansatt-navn) styres ut fra alderen til hver ansatt. Om
den ansatte er under 18 år skjules ansatt-navn. Legg merke til at samme sti i datamodellen blir brukt som
simpleBinding på ansatt-alder.
Det andre oppslaget (for å styre hidden på komponenten ansatt-alder) bruker [0] på oppslaget i datamodellen.
Dette fungerer også, men oppførselen er kanskje uventet; her skjules alle alder-komponenter dersom navnet på den første
ansatte har navnet Ola Nordmann.
Oppslag direkte på komponent tilsvarer på mange måter et oppslag mot datamodell med dataModel.
Et uttrykk som slår opp verdien til en komponent kommer til å lete etter komponenten og returnere verdien lagret på
komponenten sin simpleBinding i datamodellen. For øyeblikket støttes ingen andre verdier enn den lagret mot
simpleBinding (om andre verdier ønskes må man gå direkte mot dataModel).
Oppslag mot en komponent vil derimot returnere null dersom komponenten man slår opp verdien til er skjult (selv om
komponenten ellers har tilknyttet data i datamodellen). Dette gjør det til en viss grad mulig å styre visning av en
komponent basert på om en annen komponent er vist eller ikke. Dersom komponenten ble funnet på en helt annen (men skjult)
side gir også oppslaget verdien null selv om datamodellen har en verdi tilknyttet komponenten.
I likhet med dataModel vil oppslag mot en komponent-id forsøke å finne komponenten i nærheten av
uttrykket i kontekst av repeterende grupper. Det vil først søkes etter komponenten
i gjeldende rad, før det letes oppover i sidestrukturen.
Funksjonen formatDate tar imot en dato som første argument, og et format som andre argument. Datoargumentet er en streng,
mens formatargumentet er en valgfri streng som støtter noen tokens i
Unicode Tokens.
Dette er de tokenene vi støtter:
Enhet
Token
Resultat
Era
G..GGG
f.Kr., e.Kr.
Era
GGGG
før Kristus, etter Kristus
Era
GGGGG
f.Kr., e.Kr.
År
y
44, 1, 1900, 2017
År
yy
44, 01, 00, 17
År
yyy
044, 001, 1900, 2017
År
yyyy
0044, 0001, 1900, 2017
Forlenget år
u
-43, 0, 1, 1900, 2017
Forlenget år
uu
-43, 01, 1900, 2017
Forlenget år
uuu
-043, 001, 1900, 2017
Forlenget år
uuuu
-0043, 0001, 1900, 2017
Måned
M
1, 2,…, 12
Måned
MM
01, 02,…, 12
Måned
MMM
jan, feb, …, des
Måned
MMMM
januar, februar, …, desember
Dag i måned
d
1, 2, …, 31
Dag i måned
dd
01, 02, …, 31
Ukedag
E..EEE
man, tir, ons, …, søn
Ukedag
EEEE
mandag, tirsdag, onsdag, …, søndag
Ukedag
EEEEE
M, T, O, …, S
AM/PM
a
a.m., p.m.
Time [1-12]
h
1, 2, …, 11, 12
Time [1-12]
hh
01, 02, …, 11, 12
Time [0-23]
H
1, 2, …, 22, 23
Time [0-23]
HH
01, 02, …, 22, 23
Minutt
m
1, 2, …, 59
Minutt
mm
01, 02, …, 59
Sekund
s
1, 2, …, 59
Sekund
ss
01, 02, …, 59
Brøkdels sekund
S
0, 1, …, 9
Brøkdels sekund
SS
00, 01, …, 99
Brøkdels sekund
SSS
000, 001, …, 999
Dersom man ikke gir et format som andre argument, vil funksjonen bruke formatet dd.MM.yyyy som standard.
linkToPage-funksjonen kan brukes for å lage lenker som kan brukes inne i tekst i et skjema.
Den er ment for å lage lenker som peker til en spesifikk side av skjemaet. Å klikke på denne linken vil navigere
direkte til den spesifiserte siden.
Funksjonen tar 2 argumenter. Det første argumentet er lenketeksten som vil være synlig for
brukeren. Det andre argumentet er id-en til siden linken skal peke til.
["linkToPage", "Specify your name", "page1"]
Resultatet vil bli <a href="#/instance/<party-id>/<instance-id>/<TaskId>/page1">Oppgi navnet ditt</a>
Denne lenken vil ta brukeren til den spesifiserte siden når den blir klikket på.
linkToComponent-funksjonen kan brukes for å lage lenker som kan brukes inne i tekst i et skjema. Den er ment for å lage lenker
som peker til en spesifikk komponent i skjemaet. Å klikke på denne lenken vil navigere direkte til komponenten og gi den fokus.
Funksjonen tar 2 argumenter. Det første argumentet er lenketeksten som vil være synlig for brukeren.
Det andre argumentet er id-en til komponenten lenken skal peke til.
["linkToComponent", "Specify your name", "inputMyName"]
Resultatet vil bli <a href="#/instance/<party-id>/<instance-id>/<TaskId>/<PageId>?focusNodeId=inputMyName">Oppgi navnet ditt</a>
Denne lenken vil ta brukeren til siden komponenten er på og fokusere på den spesifiserte komponenten, når brukeren klikker på lenken.
I likhet med argv er value-funksjonen også en metode for å hente ut argumenter som er sendt inn til uttrykket.
Funksjonen kan brukes uten argumenter for å hente ut en verdi, eller med et argument for å hente ut andre
typer verdier. Dette er foreløpig tilgjengelig for
filtrering av svaralternativer og blir snart tilgjengelig
som et alternativ til argv i validering vha. uttrykk.
["value"]
Dette uttrykket henter ut verdien til svaralternativet (om brukt i filtrering av svaralternativer). I andre sammenhenger
gir dette uttrykket foreløpig en feilmelding.
["value", "label"]
Uttrykket over henter ut teksten til svaralternativet (om brukt i filtrering av svaralternativer). I andre sammenhenger
gir dette uttrykket en feilmelding.
Datatyper
Funksjoner i uttrykkene har en forventning om at argumentene som blir sendt inn har en spefikk type. Dersom et argument
blir sendt inn har en annen type enn forventet, blir verdien forsøkt konvertert til riktig type. Som et eksempel
forventer funksjonen equals to strenger, men om du sender inn den boolske verdien true som det ene eller andre
argumentet fungerer det også fint, siden den boolske verdien true blir konvertert til strengen "true".
["equals", true, "true"]
Uttrykket over fungerer, og gir true som resultat (fordi true og "true" sammenlignes som samme verdi ved at
true konverteres til "true" før sammenligningen). Dette gjør også at du kan kalle en funksjon som returnerer en
datatype og f.eks. sammenligne med en helt annen datatype. Les mer om hvilke datatyper som kan konverteres til hva
under.
Alle funksjoner som forventer en spesifikk datatype som argument vil også kunne fungere om man sender
inn null, men noen steder vil en null-verdi gi en feilmelding - for eksempel om man prøver å slå opp i
datamodellen med ["dataModel", null]. I concat-funksjonen vil derimot en null-verdi bli tolket som en tom streng.
Strenger
Strenger inneholder vilkårlig tekst, og er en bred datatype som tall og boolske verdier kan konverteres til.
Noen strenger kan også konverteres til andre datatyper:
Alle andre strenger enn de i tabellen over vil gi feilmelding om de blir forsøkt konvertert til andre typer.
Tall
Tallverdier gjelder positive og negative heltall og desimaltall. Noen strenger blir også konvertert
automatisk til en tallverdi, som vist i tabellen til strenger over. For at konvertering av en streng til et tall
skal fungere, må strengen oppfylle følgende:
Strengen inneholder bare et tall, ingen annen tekst foran/bak tallet
Negativt fortegn (-) kan brukes, men positivt fortegn (+) støttes ikke.
Desimaltall må representeres med punktum, ikke komma.
Tusenskilletegn eller annen tallformattering støttes ikke.
Alle andre strenger vil gi en feilmelding om de blir forsøkt konvertert til et tall. Forsøker man å konvertere en
boolsk verdi til et tall, gir det også en feilmelding.
Funksjoner som forventer å få inn et tall kan også få inn null. Se mer om hvilken effekt det har under
beskrivelsen til hver funksjon.
Boolske verdier
Boolske verdier omfatter true (sann) og false (usann). Når man kaller en funksjon som forventer å få inn en boolsk
verdi, kan man også sende inn enkelte andre typer, som blir konvertert til en boolsk verdi:
Tallene 1 og 0 fungerer som henholdsvis true og false
Strengene "1" og "0" fungerer likt som tallene (og blir henholdsvis true og false)
Strengene "true" og "false" konverteres også til en boolsk verdi
Alle andre verdier gir en feilmelding om de blir sendt til en funksjon som forventer en boolsk verdi. Legg merke til
at disse reglene er litt forskjellige fra reglene til strenger. Det er dermed forskjell på hvilke verdier
som kan tolkes som en boolsk verdi for en funksjon som forventer et boolsk argument - og hvilke verdier som er like
en boolsk verdi. Funksjonen equals sammenligner verdier som strenger, og dermed vil tallet 1 og
strengen "1" sammenlignes som like, men den vil ikke gjenkjenne 1 og true som like verdier.
Det kan kanskje se ut som følgende uttrykk er like:
Hvis verdien (her gitt fra oppslaget ["dataModel", "hideName"]) er true eller "true" vil
komponenten skjules, men dersom verdien er 1 eller "1" vil komponenten bare skjules med uttrykkene i alternativ
1 og 3. Dette fordi resultatet i uttrykket for hiddenkonverteres til en boolsk verdi, og
ifforventer en boolsk verdi som første argument. Derimot vil equals sammenligne verdiene som strenger,
og "1" er ikke lik "true".
De fleste steder hvor man forventer å få inn en streng, tall eller
boolske verdier skal også tåle en null-verdi. Null-verdier indikerer at en spesifikk verdi
mangler, og det er forskjell på f.eks. en null-verdi, en tom streng og tallet0.
Dersom man gjør et oppslag i en funksjon som dataModel, og verdien man leter etter ikke finnes/er satt, vil som regel
null bli resultatet.
Tips og triks
Vise/skjule hele sider
Uttrykk kan brukes til å vise/skjule hele sider. I eksempelet under vil hele siden skjules dersom en komponent
(på en av de andre sidene) har verdien no eller ikke er satt.
Dersom siden man stod på blir skjult, vil applikasjonen automatisk gå videre til neste tilgjengelige side
i side-rekkefølgen. Om alle de neste sidene er skjult, vises den første mulige
siden i rekkefølgen istedenfor.
Streng eller mindre streng sammenligning?
Måten uttrykkene kjøres på gjør at de kan virke litt strenge (ved at f.eks. 0 og null er ulike verdier når man
sammenligner med equals). Det er et designvalg gjort i Altinn av to grunner:
Strenge regler er tydelige regler. Uttrykkene vil heller gi en feilmelding om noe ikke er som forventet, enn å la deg
lure på hvorfor det ble slikt det ble.
Hvis uttrykkene behandler mange ulike verdier som like, fratar vi deg muligheten til å skille mellom dem om du skulle
ønske det.
Om man ønsker mindre streng sammenligning, kan man f.eks. konstruere et uttrykk som bruker or-funksjonen
til å gjenkjenne flere forskjellige verdier:
Husk også at konvertering til boolsk verdi tillater flere alternativer enn strenger
(som equals forventer). Siden funksjonen or forventer boolske verdier som argumenter, og verdiene
0, false og null allerede tillates som boolske verdier vil følgende fungere likt som uttrykket over: