Altinn / app-frontend-react

Altinn application React frontend
BSD 3-Clause "New" or "Revised" License
16 stars 24 forks source link

Binde MultipleSelect/Checkboxes til en repeterende gruppe i datamodellen #1497

Open StianVestli opened 8 months ago

StianVestli commented 8 months ago

Description

Veldig mange av de repeterende gruppene vi benytter , så bygges den opp i kode fra en optionliste. Vi ønsker at gruppen populeres opp med rader automatisk fra en optionliste.

image

Man må da kunne sette opp att man vil vise teksten fra optionlista i gruppen mens verdien må kunne settes mot et felt i datamodellen.

Oppdatert beskrivelse (ref møte 25. april 2024):

Tildels også beskrevet i kommentar under.

Vi har diskutert løsninger for denne oppgaven, og det vi ser for oss er å kunne knytte multi-valg-options-komponenter (foreløpig Checkboxes og MultipleSelect) til en repeterende gruppe struktur i datamodellen. Det vil si, når man velger en ny option, oppretter det en ny rad i datamodellen, og når man fjerner et valg fjerner det raden. Da kan man også knytte en RepeatingGroup til samme sted i datamodellen, og dermed be brukeren fylle ut mer info om hvert av de valgene man gjorde tidligere i Checkboxes/MultipleSelect-komponenten.

Ting man bør tenke på:

Additional Information

olemartinorg commented 8 months ago

Interessant! 🤔 Noen kontrollspørsmål:

  1. Bygges rep.grupper opp slik at alle opsjoner i en options-liste i utgangspunktet fører til en rad i rep.gruppa, eller er det slik at f.eks. opsjonene man har krysset av for i en checkbox-gruppe tidligere i skjemaet oppretter rader i rep.gruppa?
  2. I use-casene dere jobber med, er det slik at brukeren selv kan fjerne rader og legge til egne? Hva forventes det da at skal stå i feltet for opsjons-verdi når brukeren har opprettet raden selv?

Å ha full støtte for dette fordrer vel også at man har teksten tilgjengelig på en eller annen måte. Akkurat nå tror jeg det vil funke om man f.eks. putter en Dropdown-komponent inne i gruppa, knytter den mot opsjons-verdien i datamodellen (og opsjonslista), men skjuler den permanent. Da vil den fortsatt kunne vises i tabellen (whoops, vår feil - vi burde nok ikke vist skjulte komponenter der!).

Ellers er jeg redd vi mangler en liten (men viktig) byggekloss for å kunne implementere dette i app-frontend: Vi kan ikke lagre noe permanent sted det vi trenger å lagre av metadata for at dette skal fungere. Se for eksempel for deg at man åpner appen første gang, og rep.gruppa fylles ut med opsjoner - det scenarioet er identisk med om brukeren sletter alle radene som ble fyllt ut og laster siden på nytt. Så lenge vi ikke kan lagre noe sted at "vi har fyllt ut alt en gang, så ikke gjør det igjen" kan vi ikke hindre slikt. Ved å implementere dette i kode på backend derimot, kan man utvide datamodellen til å inkludere metadata om slikt. Det er vanskeligere for oss på frontend å utvikle noe med en antakelse om at noe er tilgjengelig i datamodellen for å støtte det vi skal gjøre, og at formatet der er likt det vi trenger.

StianVestli commented 8 months ago
  1. Vi har i grunn begge deler som skjer i skjemaene våre. Men med hiddenrow muligheten så kan vi nå bygge fulle grupper og filtrere vekk det som man ikke har valg i såfall på en sjekkliste. siden man nå støtter contains.
  2. Ja i noen settinger så må bruker kunne legge til flere rader sjølv, dette løser vi i dag ved da å vise et inputfelt dynamisk. trikset med dropdown lista er vel det vi ratt gjør i dag, for å vise en verdi... Men det selve jobben for å populerer opp gruppen som er litt knotete i dag, siden man vil ofte bygge denne fra enten en json option liste eller via api. Man tillater som regel ikke at bruker kan slette det som er preutfylt, men bare det som brukern legger inn sjølv.

Så dere kan ikke sjekke om det finnes noe i gridden? for hvis det ligger noe der så burde en ikke bygge det på nytt.

olemartinorg commented 8 months ago

Lurt med hiddenRow til det bruket, ja! 🙌

Man tillater som regel ikke at bruker kan slette det som er preutfylt, men bare det som brukern legger inn sjølv.

Det betyr jo at om app-frontend skal konstruere gruppene basert på options, må vi også legge til noe data om at raden er preutfylt (og hva det feltet heter i datamodellen og hvordan det er forventet at dataene ser ut vil jo variere per datamodell). I tillegg er det nok litt i konflikt med en retning vi ønsker å gå - for vi vil begrense mulighetene frontend har for å gjøre endringer i datamodellen. Det er f.eks. ikke ønskelig at frontend skal kunne endre på en sti i datamodellen som ikke er bundet til noen komponenter som frontend da skal kunne manipulere. Altså, hvis man har et skjult hjelpefelt i datamodellen, et felt som er knyttet til en readOnly-komponent, eller en repeterende gruppe som er knyttet til en komponent som har skrudd av legg til-knappen, skulle egentlig backend også ha nektet å ta imot en lagringsforespørsel fra frontend hvor man prøver å endre/legge til data disse stedene i datamodellen.

Med andre ord, jeg mener kanskje det mest korrekte stedet å gjøre en slik operasjon er på backend, og det er jo det man gjør i dag når man skriver custom kode for slikt. Men det er helt klart mulig at vi skulle laget verktøy i backend for å gjøre en slik operasjon enklere for dere å implementere (hvis det skjer ofte).

Så dere kan ikke sjekke om det finnes noe i gridden? for hvis det ligger noe der så burde en ikke bygge det på nytt.

Jo, men fra vårt perspektiv er det ingen forskjell på de to scenarioene:

EDIT: Også relevant:

olemartinorg commented 8 months ago

Jeg har tenkt litt mer på denne, og jeg tenker det er fullt mulig for oss å lage noe av dette, men da spesielt en begrenset variant hvor vi knytter en multiple choice options-komponent (altså MultipleSelect eller Checkboxes) sammen med en repeterende gruppe slik at frontend holder disse i synk. Altså, hvis du krysser av noe i Checkboxes oppretter det en tilsvarende repeterende gruppe, krysser du det vekk igjen fra Checkboxes fjerner vi gruppa.

Noe slikt kunne vi kalt at gruppa blir "styrt av" en options-komponent, men dette måtte hatt noen begrensinger:

Jeg er fortsatt usikker på dette med om bruker skal få opprette egne rader, og hvordan det da vil fungere. Det kan fungere til en viss grad, men hvis man f.eks. har en nedtrekksliste med options inne i gruppa for å velge hvilket av alternativene denne raden gjelder må det nødvendigvis også kommunisere dette valget tilbake til Checkboxes/MultipleSelect slik at det alternativet blir valgt der også. I den perioden hvor brukeren ikke har valgt noe i nedtrekkslista inne i gruppa er den gruppe-raden i limbo - hvis feltet er tomt kan vi ikke røre disse radene når vi automatisk sletter rader fra rep.gruppa ved oppdateringer fra checkboxes/multipleselect.

Hmm, joda, dette kan funke, og det kan funke ganske bra, tror jeg. Det kan potensielt konfigureres i checkboxes/multipleselect med en one-liner:

[
  {
    "id": "velgReiseMaal",
    "type": "MultipleSelect",
    "optionsId": "land",
    "dataModelBindings": {
      "simpleBinding": "MineReiseMaal",
      "group": "ReiseMaal.Land"
    }
  },
  {
    "id": "reisemaal-gruppe",
    "type": "Group",
    "dataModelBindings": {
      "group": "ReiseMaal"
    },
    "maxCount": 999,
    "children": [
      "begrunnelse"
    ]
  },
  {
    "id": "begrunnelse",
    "type": "TextArea",
    "dataModelBindings": {
      "simpleBinding": "ReiseMaal.Begrunnelse"
    },
    "textResourceBindings": {
      "title": [
        "concat",
        "Hvorfor vil du reise til ",
        ["optionsLabel", "velgReiseMaal", ["dataModel", "ReiseMaal.Land"]],
        "?"
      ]
    }
  }
]

Den viktige biten her er at MultipleSelect-komponenten har en group binding også. Strengt tatt er det da ikke helt nødvendig med simpleBinding lengre heller, for hele tilstanden til komponenten kan lagres i gruppe-bindingen istedenfor. På sett og vis bør vi kanskje bare tillate en binding av gangen, for hvis ikke må vi bestemme oss for hva som skal skje dersom vi laster en datamodell hvor det er en konflikt mellom bindingene. (Skal vi slette data fra simpleBinding eller fra group-bindingen for å ende opp med gyldig resultat? Hvilken er 'master'? Det gir ikke helt mening, vi burde bare tillate en av dem).

Bemerk at dette går ut ifra to ting, på et rent teknisk nivå:

StianVestli commented 8 months ago

Jeg trur dette kan være en løsning, hvis jeg skjønte litt av dette her :). Men man bør kunne skjule checkbokslista, og egentlig kunne si at alle valg er valgt som default. Det siste kan vel også gjøres i kode, men det er ofte slik at man sitter på en liste der alle valg skal besvares i en rep gruppe.

olemartinorg commented 8 months ago

Åh! Haha, her ser jeg at det jeg beskrev nok var en liten sidevei og beskrev en løsning på et litt annerledes behov enn det du tenkte på, ja.

Vi kan nok støtte det du beskriver også, men ikke sammen med muligheten for å slette/legge til egne rader. Da mener jeg det må inn i instansieringen (og på backend), hvis ikke blir det fort både litt knotete og sårbart å gjøre det i frontend. I tillegg blir det altså vanskelig å vite om en helt tom rep.gruppe betyr at brukeren har slettet alt eller om vi jobber med en helt ny instans/datamodell.

olemartinorg commented 7 months ago

Delvis relatert (iallefall til den løsningen jeg snakket om, men kanskje ikke helt den løsningen Stian her tenkte på):