Edellisessä kirjoituksessa nähtiin, miten asiat voivat mennä pieleen galleria-kontrollin tietoja päivitettäessä. Tällä kertaa käydään läpi kaksi erilaista tapaa rakentaa muokattava taulukko (editable grid).
Siten että päivitetyt tiedot myös tallentuvat aina oikein.
Vaihtoehto 1 – Muokataan yhtä riviä kerrallaan
Yksinkertaisinta on rajata toiminnallisuutta siten, että käyttäjä voi muokata ainoastaan yhtä riviä kerrallaan.
Toteutetaan sellainen.
Jatketaan edellisen kirjoituksen tilauslista esimerkkiä. Lisätään gallerian riville painike, jota painettaessa tallennetaan muuttujaan (varEditRow), kyseisen rivin Id.
OnSelect: UpdateContext({varEditRow: ThisItem.ID})
Asetetaan määrä ja hinta -kenttien DisplayMode arvo riipumaan siitä, onko kyseisellä rivillä painettu Muokkaa-painiketta. Mikäli painiketta on painettu, ovat kentät muokattavia (DisplayMode.Edit). Muussa tapauksessa ne ovat tavallisia tekstikenttiä (DisplayMode.View).
Seuraavaksi lisätään riville painikkeet tallennusta ja perumista varten. Ne näkyvät ainoastaan muokattavalla rivillä.
Visible: varEditRow = ThisItem.ID
Käyttäjä voi Peru-painikkeella palauttaa rivin katselutilaan (tallentamatta muutoksia). Tämä tehdään asettamalla muokattavan rivin Id:ksi -1 (sellaista riviä ei ole olemassa).
Tallenna-painikkeen painaminen tallentaa tiedot ja palauttaa rivin katselutilaan (eli asettaa muokattavan rivin Id:ksi -1).
Ratkaisu toimii näinkin, mutta viimeistellään käyttökokemusta vielä hieman. Piilotetaan muokkaa-painikkeet aina, kun riviä ollaan muokkaamassa (varEditRow ei ole tyhjä eikä -1).
Asetetaan Tallenna ja Peru -painikkeet ilmestymään tarkalleen Muokkaa-painikkeen päälle.
Lopuksi himmennetään riviä muokattaessa kaikki muut rivit. Tämä onnistuu läpikuultavalla harmaalla laatikolla (rectangle), joka näkyy kaikilla muilla paitsi muokattavalla rivillä (ThisItem.ID <> varEditRow).
Ja ainoastaan jos jotain riviä muokataan (varEditRow > 0).
Valmis toteutus näyttää tältä.
Ratkaisu on yksinkertainen ja suorituskykyinen (päivitetään kerrallaan ainoastaan yksi rivi). Ja se toimii riippumatta siitä, miten paljon galleriassa on rivejä.
Tämä soveltuu mainiosti tilanteeseen, jossa rivejä ei juurikaan muokata.
Entä jos sovelluksen koko idea on useiden rivien lisääminen ja muokkaaminen?
Vaihtoehto 2 – Muokkaustiedon ylläpito kokoelmassa
Mikäli halutaan muokata useita rivejä nopeasti ja tallentaa kaikki tehdyt muutokset kerralla lopuksi, löytyy ratkaisu kokoelmasta (collection).
Lyhyesti
- Tallennetaan riviä muokatessa rivin Id sekä sen uudet arvot kokoelmaan
- Tallennuksessa käydään kokoelma läpi ja tallennetaan kaikkien sieltä löytyvien rivien arvot
Aloitetaan.
Muokataan aluksi galleriaa siten, että määrä-kentän arvoa muutettaessa (OnChange), lisätään kokoelmaan (colUpdatedItems) päivitetyn rivin tiedot (Id, määrä, hinta ja rivin kokonaisarvo).
Collect( colUpdatedItems, { Index: ID, Qty: txtQtyValue_1.Text, Price: txtQtyValue_1.Text, totalValue: txtQtyValue_1 * txtPriceValue_1 } )
Nyt kokoelmaan syntyy uusi rivi jokaisella rivin muokkauskerralla. Haluamme tietenkin kokoelmassa olevan jokaista gallerian riviä kohden maksimissaan yhden rivin.
Tarkistetaan siis ensin löytyykö kokoelmasta päivitettyä riviä vastaava rivi. Mikäli löytyy, päivitetään olemassaolevaa riviä. Muussa tapauksessa lisätään sellainen.
If( IsBlank( LookUp( colUpdatedItems, Index = ThisItem.ID ) ), Collect( colUpdatedItems; { Index: ID, Qty: txtQtyValue_1.Text, Price: txtQtyValue_1.Text, totalValue: txtQtyValue_1 * txtPriceValue_1 } ), Patch( colUpdatedItems, {Index: ID}, { Qty: txtQtyValue_1.Text, Price: txtQtyValue_1.Text, totalValue: txtQtyValue_1 * txtPriceValue_1 } ) )
Sama toimenpide tulee tehdä myös rivin hintaa päivitettäessä. Emme kuitenkaan halua kopioida äsken kirjottamaamme koodia useaan paikkaan. Koska se on tyhmää.
Koodin kopioimisen voi välttää lisäämällä riville painikkeen, jonka OnSelect-tapahtumassa tehdään rivin tietojen tallennus kokoelmaan. Eli kopioidaan sinne juuri kirjoittamamme koodi ja poistetaan se kentän OnChange-tapahtumasta.
Tämän jälkeen määrä ja hinta -kenttien OnSelect-tapahtumassa virtuaalisesti painetaan tätä painiketta (Select(btnUpdateCollection)).
Nyt kokoelman päivityskoodi on ainoastaan yhdessä paikassa.
Painike tietenkin piilotetaan käyttäjältä (visible = false).
Lisätään vielä painike, jolla tehdyt muutokset tallennetaan kerralla tietovarastoon.
ForAll( colUpdatedItems, Patch( update100item, {ID: Index}, { quantity: Qty, price: Price, value: totalValue } ) )
Tallentamisen jälkeen tyhjennetään kokoelma (Clear(colUpdatedItems)).
Näin kaikki käyttäjän tekemät muutokset tallentuvat. Riveistä päivitetään ainoastaan ne, joita on muokattu.
Mikäli muutoksia on tehty paljon, niiden tallennus kestää. Tallennuksen edetessä PowerApps päivittää gallerian rivejä. Tämä saattaa käyttäjästä näyttää oudolta.
Käyttäjälle onkin parempi näyttää tallennuksen ajan ”odota hetki” -ruutua.
Lisätään tallennuksen alkuun ja loppuun rivit, joilla päivitetään uuden ikkunan näkyvyyttä säätelevän muuttujan arvoa.
UpdateContext({showWaitScreen: true})
Rakennetaan Odota hetkinen -ikkuna lisäämällä näytölle
- koko näytön kokoinen valkoinen läpikuultava laatikko
- valkoinen mustareunainen laatikko varsinaista ilmoitusta varten
- ilmoitusteksti
- animoitu kuvake kuvaamaan että jotain tapahtuu
Ja asetetaan niiden kaikkien näkyyvys riippumaan muuttujasta.
Visible: showWaitScreen
Lopputulos näyttää tältä
Yhteenveto
Muokattavaa taulukkoa rakentaessa on syytä pitää mielessä yksi asia. PowerAppsissa rivin tallentaminen kestää. Käytännössä noin 0,5 – 1 sekuntia per rivi.
Se on tietokoneelle iäisyys.
Odotusajan voi pilkkoa pieniin osiin antamalla käyttäjän muokata ainoastaan yhtä riviä kerrallaan ja tallentamalla muutokset samantien (vaihtoehto 1).
Tai sitten käyttäjän voi antaa rauhassa muokata haluamansa rivit ja tallentaa kaikki muutokset kerrallaan. Näin muutosten tekeminen on nopeampaa, mutta lopuksi joutuu odottamaan kerralla pidempään (vaihtoehto 2).
Tai sitten viritetään tallennus toimimaan siten, että muutokset tallennetaan rinnakkain eikä peräkkäin. Tämä tehdään seuraavassa kirjoituksessa.