Programmering i App Lab Modul 9 af 10 · Blokoversigt · Tastatur

Modul 9

Gem data

Dine apps har indtil nu glemt alt, hver gang fanen blev lukket.

Det skal du bygge

En highscore-liste. Brugeren taster navn og score og trykker gem. Listen overlever, at appen lukkes, og den er fælles for alle, der bruger appen.

Anna 120 Gem score Sofia: 145
Anna: 120
Mikkel: 95

Opret tabellen først

Gør det her, før du skriver en eneste blok. Ellers virker koden ikke, og fejlmeddelelsen fortæller dig ikke hvorfor.

  1. Find Data-fanen

    Øverst i App Lab er der tre faner: Design, Kode og Data. Du har kun brugt de to første indtil nu.

  2. Opret tabellen

    Klik Add table og kald tabellen highscores. Du behøver ikke oprette kolonner. De bliver lavet automatisk ud fra de felter, din kode sender.

Blokkene du skal bruge

createRecord("table", record, …)
Hedder createRecord · Data (limegrøn) Gemmer én ny række i tabellen.
readRecords("table", terms, …)
Hedder readRecords · Data (limegrøn) Henter rækker ud igen. Du får dem som en liste.

Data-kategorien er den limegrønne, ikke den grønne. Den grønne er Functions. Kig efter, om der står Data eller Functions ved siden af firkanten.

Værktøjskasse → Data → createRecord("table", record, …)

Byg det

  1. Design

    To Text Inputs med id navnFelt og scoreFelt, en Button med id gemKnap, en Button med id hentKnap og en høj Label med id listen.

  2. Gem en score

    Træk createRecord("table", record, …) ind i en onEvent. I det andet hul beskriver du, hvad der skal gemmes.

    Blokken kommer med ét par i forvejen. App Lab er på engelsk, så der står {name: 'Alice'}. Det er en kolonne: overskriften name og værdien 'Alice'. Du skal have to kolonner, så du skal skrive parret om og tilføje ét mere.

    Formlen for ét par er altid den samme:

    "Overskrift":variabel

    • Overskriften står i anførselstegn. Det er navnet på kolonnen i Data-fanen, og det er den, brugeren kommer til at se, så skriv den med stort. Anførselstegnene er der af en grund: uden dem må overskriften ikke indeholde æ, ø eller å.
    • Værdien står uden anførselstegn, når det er en variabel. Skriver du "navn" med anførselstegn, gemmer du ordet navn i hver eneste række i stedet for det, brugeren tastede.
    • Flere par adskilles med komma, og det hele står inde i de samme krøllede parenteser.

    Så slet name: 'Alice' og skriv i stedet:

    {"Navn":navn, "Score":point}

    Krøllet parentes, første par, komma, andet par, krøllet parentes. Vil du senere gemme en tredje ting, sætter du bare endnu et komma og endnu et par ind før den sidste krøllede parentes.

    Læg mærke til, at "Navn" og navn ikke er det samme ord. "Navn" med stort er overskriften på kolonnen. navn med lille er din variabel fra linjen ovenover. At de ligner hinanden er praktisk, når du læser koden, men computeren skelner skarpt mellem stort og lille.

    Overskriften skal staves præcis ens, når du senere henter rækkerne ud igen. Gemmer du under "Navn", skal du hente med records[i].Navn. Skriver du records[i].navn, får du ingenting.

    onEvent(@"gemKnap", @"click", function() { var navn = getText(@"navnFelt"); var point = getNumber(@"scoreFelt"); createRecord("highscores", {"Navn":navn, "Score":point}, function(record) { setText(@"listen", "Gemt!"); }); });

    Kør, tast et navn og en score, og tryk gem. Skift til Data-fanen, og rækken står der. Luk fanen og åbn projektet igen: den står der stadig.

  3. Hent alle scorer

    readRecords("table", terms, …) henter rækkerne ud igen. Det tomme {} i midten betyder "alle sammen, ingen filtrering".

    onEvent(@"hentKnap", @"click", function() { readRecords("highscores", {}, function(records) { setText(@"listen", records.length + " scorer gemt"); }); });
  4. Vis dem som en liste

    records er en liste, ligesom i modul 5, så du kan køre en for-løkke igennem den, som i modul 6. Forskellen er, hvad der ligger på pladserne. I modul 5 lå der tekst. Her ligger der en hel række på hver plads, med både Navn og Score i sig.

    onEvent(@"hentKnap", @"click", function() { readRecords("highscores", {}, function(records) { var tekst = ""; for (var i = 0; i < records.length; i++) { tekst = tekst + records[i].Navn + ": " + records[i].Score; tekst = tekst + "\n"; } setText(@"listen", tekst); }); });

    records[i].Navn betyder: tag række nummer i, og hent feltet Navn ud af den. Læg mærke til, at det er to skridt med hver sin måde at pege på: den kantede parentes finder en plads i listen med et nummer, som i modul 5, og punktummet finder et felt inde i rækken med et navn.

    For-løkken sidder inde i callback-funktionen, som sidder inde i onEvent.

Hvorfor virker det

En database er en samling data, der gemmes permanent, også når appen lukkes, og også for andre brugere end dig. App Labs database minder om et regneark:

idnavnscore
1Anna120
2Mikkel95
3Sofia145

Hvorfor er der en ekstra grøn funktion?

Både createRecord og readRecords har en grøn function hængende bag på sig, ligesom onEvent har haft det siden modul 1. Grunden er den samme begge steder: det tager tid.

Databasen ligger ikke i din browser, men på en server, og der går et øjeblik, før svaret kommer tilbage. App Lab står ikke og venter. Den kører videre og kalder først din grønne funktion, når svaret er ankommet. Sådan en funktion kaldes en callback.

Derfor skal alt, der bruger data fra databasen, ligge inde i den grønne funktion. Lægger du det udenfor, kører det, før svaret er kommet, og der er ingenting at arbejde med.

readRecords("highscores", {}, function(records) { var antal = records.length; }); setText(@"listen", antal);
Forkert. setText kører længe før svaret kommer, og antal findes slet ikke uden for den grønne funktion.

De fire ting man kan gøre ved data

Blokkene i Data-kategorien dækker fire handlinger. De er de samme i enhver database:

Prøv selv

Opgave

Udvid highscore-listen

  1. Gem også en dato sammen med hver score. Du kan bruge getTime() fra Control, eller bare lade brugeren taste den.
  2. Vis kun scorer over 100. Du skal bruge en if-blok inde i for-løkken.
  3. Vis den højeste score øverst i sin egen label. Gennemgå listen med en for-løkke og hold styr på den største, du har set indtil videre. Det er opsamler-mønsteret fra modul 6.

Udfordring

Hent kun bestemte rækker ved at udfylde det tomme {}: readRecords("highscores", {"Navn":"Anna"}, ...) henter kun Annas rækker. Byg en søgefunktion med et Text Input.

Til eksamen

  1. Forskellen på en variabel og en database, altså hvad der huskes hvor længe.
  2. Hvad en tabel, en record og et felt er.
  3. Hvorfor createRecord og readRecords har en callback-funktion.
  4. Hvorfor kode, der bruger data fra databasen, skal ligge inde i callbacken.

Byggeklods: gem og hent

onEvent(@"gemKnap", @"click", function() { var vaerdi = getText(@"mitFelt"); createRecord("minTabel", {"Felt":vaerdi}, function(record) { setText(@"status", "Gemt"); }); }); onEvent(@"hentKnap", @"click", function() { readRecords("minTabel", {}, function(records) { var tekst = ""; for (var i = 0; i < records.length; i++) { tekst = tekst + records[i].Felt + "\n"; } setText(@"listen", tekst); }); });