Tee yksinkertainen inflaatiolaskuri käyttäen mallina Laskin-esimerkkiä. Aloita luomalla Angular CLI:llä uusi projekti nimeltään "ang-inflacalculator" komennolla: ng new ang-inflacalculator --minimal -t=false -s=false. Sovellus toimii siten että lomakkeelle syötetään tuotteen tai palvelun nykyinen hinta ja inflaatioprosentti. Tuloksena saadaan tuotteen tai palvelun uusi hinta inflaation vaikutuksen jälkeen. Pyöristä laskettu uusi hinta kahden desimaalin tarkkuuteen.
Laskuri voisi näyttää suunnilleen tältä.
Jatketaan ensimmäisessä tehtävässä tehtyä inflaatiolaskuria. Tee
laskuriin uusi komponentti, jonka nimeksi voit antaa vaikkapa
calculator2.component. Tee app.componentin otsikon alle linkit,
joista pääset kahteen lapsikomponenttiin reitityksen avulla (kts.
reititysesimerkki). Tee
calculator2:een laskuri, jonka lomakkeelle syötetään vanha hinta
ja uusi hinta, joista lasketaan inflaatioprosentti.
Tee sovellukseen vielä calculator.service komennolla ng g
service calculator. Siirrä molemmista lapsikomponenteista
laskumetodit serviceen, liitä service komponentteihin dependency
injectionilla (esimerkki),
ja kutsu servicen metodeja komponenteissa. Sovelluksen toiminta ei
siis muutu, mutta arkkitehtuuri paranee, koska laskumetodit eivät
ole enää eri komponenteissa, vaan servicessä.
Laskuri voisi näyttää suunnilleen tältä.
Tee Angularin Learn Angular -tutoriaali. Älä tee tutoriaalia webbisivulla olevaan editoriin, vaan omalle koneelle. Aloita luomalla Angular CLI:llä uusi projekti nimeltään "ang-tutorial1" komennolla: ng new ang-tutorial1 --minimal -t=false -s=false. Huomaa että omalle koneellesi syntyvässä sovelluksessa komponentit muodostuvat kolmesta erillisestä tiedostosta (TS-luokka, HTML-templaatti ja CSS-tiedosto), kun taas tutoriaalissa komponentin osat ovat yhdessä tiedostossa. Käytämme kolmea erillistä tiedostoa, sillä se on SoC-periaatteen (Separation of Concerns) mukaisesti parempi käytänne.
Tutoriaali muodostuu monista pienistä tehtävistä, joista jokaisessa tutustutaan johonkin Angularin peruspiirteeseen. Tee kaikki tehtävät samaan Ang-tutorial1 -sovellukseen. Sovellukseen tulee app-komponentti ja sen sisälle neljä komponenttia: child, comments, home ja user. Jätä app-komponentin taustaväri valkoiseksi ja tee muille komponenteille taustaväri, niin että erotat niiden paikat. Kuvan optimointitehtävässä voit käyttää tätä kuvaa, joka pitää laittaa sovelluksen public-kansioon.
Kommentoi jokaisen luomasi tiedoston alkuun, mikä on kyseisen tiedoston rooli sovelluksessa. Esim. kun teet komponentin, kirjoitat sen TS-luokan alkuun /* Tämä on komponentin luokkaosa, joka sisältää sovelluslogiikan ja jossa olevat propertyt voidaan bindata... jne */. Samaa asiaa ei tarvitse selittää enää muissa komponenteissa, vaan riittää kun teet yhden kommentin jokaisen sellaisen tiedoston alkuun, jolla on erilainen rooli.
Tee projektin juureen erillinen tekstidokumentti jossa vastaat seuraaviin kysymyksiin:
➤ Ratkaisun toiminta web-sivulla.
Tehdään dynaaminen, datasta automaattisesti rakentuva, kotisivusto Angularilla. Aloita luomalla Angular CLI:llä uusi projekti nimeltään "ang-homepage" komennolla: ng new ang-homepage --minimal -t=false -s=false.
Sovellus koostuu kolmesta komponentista: 1) äitikomponentti (app.component.ts), jonka sisällä ovat: 2) navigaatiopalkki (navbar.component.ts), jossa on linkit SPA-näkymiin (minä, opinnot ja harrastukset) ja 3) kotisivu (page.component.ts), jossa on sivun nimi, kuva ja tietoja minusta, opinnoista tai harrastuksista. Lisäksi sovelluksessa on in-memory-data-service.ts -valepalvelin ja content.service.ts, joka tarjoilee valepalvelimella olevan datan kotisivukomponentille ja navigaatiopalkille.
Kotisivujen sisältö haetaan feikatulta palvelimelta, joka luodaan angular-in-memory-web-api -kirjaston avulla. Asenna kirjasto projektiisi. In-memory-web-api otetaan käyttöön konfiguraatiotiedostossa, jonka malli on tässä: app.config.ts. Laita projektisi app-kansioon sitten tämä in-memory-data.service.ts -valepalvelin.
Mallin content.service.ts:n tekemiseen ja sen käyttämiseen komponenteissa saat tästä esimerkistä. Tiedon haku palvelimelta observablena httpClient-oliolla ei paljonkaan eroa tiedon hausta promisena fetch()-metodilla.
Navigaatiopalkin linkkien id:t ja nimet haetaan valepalvelimelta contentservicen avulla. Malli navigaatiolinkkien tekemiseen: navbar.component.html.
Koska "kotisivujen" vaihtuvat SPA-näkymät ovat muodoltaan samanlaisia, teemme vain yhden kotisivu-komponentin (page.component.ts), jonka sisältö vaihtuu id:n perusteella. Kotisivu-komponentin HTML-templaatissa on ylinnä sivun nimi, sen alla kuva, ja sen alle on listattu allekkain kolme "faktaa". Tässä valmiina page.component.ts, jonka koodista selviää kuinka sisällön vaihtaminen id:n perusteella tapahtuu. Kuvat saat tästä, laita ne public-kansioon. Koko sovelluksen tyylit saat tästä.
Kun sovellus toimii, voit kokeilla lisätä in-memory-data.serviceen uuden "sivun" datan, eli olion jonka id on 4. Huomaat, että sovellukseen rakentuu automaattisesti datasta uusi "sivu" ja sen linkki.
Jos sovelluksen rakentaminen yllä olevilla ohjeilla ei onnistu, niin voit kopioida sovelluksen tärkeimmät tiedostot tästä zip-paketista.
Tee lopuksi tekstitiedosto "tiedonkulku.txt", jossa kuvaat sovelluksen tiedonkulun, eli "palvelimella" olevan sisällön siirtymisen HTML-sivulle katseltavaksi. Kerro myös, miksi tiedonkulku on toteutettu tällä tavalla? Tehtävässä molempiin komponentteihin siirtyy palvelimelta koko content-taulukko. Jos haluaisit hakea palvelimelta vain sen tiedon, mitä komponentit käyttävät, niin kuinka toimisit?
Tee Angularin Build your first Angular app -tutoriaali. Älä tee tutoriaalia webbisivulla olevaan editoriin, vaan omalle koneelle. Tutoriaalissa annetaan sovelluksen aloitusrunko, mutta älä käytä sitä, vaan käytä tätä aloitusrunkoa, tai tee aloitusrunko itse (ohje alla). Mediaelementit ovat public/assets -kansiossa, mikä on niiden suositeltava sijainti. Aloitusrungossa ovat mukana lisäksi koko sovelluksen tyylit ja app-komponentin tyylit.
Voit halutessasi tehdä myös aloitusrungon itse, esim. komennolla ng new ang-tutorial2 --minimal -t=false -s=false. Kopioi tällöin assetit public/assets kansioon, koko sovelluksen tyylit styles.css -tiedostoon ja app-komponentin tyylit sen css-tiedostoon.
Huomaa, että kun lähdet tekemään tutoriaalia omaan
aloitusrunkoon, niin komponentit muodostuvat kolmesta osasta. Kun
kopioit tutoriaalista komponentin HTML-koodia, laita se aina
komponentin HTML-tiedostoon. Älä laita sitä TS-luokan sisään,
kuten tutoriaalissa tehdään. Aloita tutoriaalin tekeminen Home-komponentin
luomisesta.
Jos tutoriaalin tekeminen ei meinaa onnistua, niin tässä on valmiiksi tehty tutoriaali,
johon voit verrata tekemääsi koodia. Tutoriaalista puuttuvat alla
olevat muutokset b), c) ja d).
Kyseessä on vuokrattavia kiinteistöjä esittelevä sovellus, jossa voi hakea ja tarkastella kiinteistöjä ja lähettää yhteydenottopyynnön. Tee ensin tutoriaali valmiiksi. Huomaa että db.json-tiedoston sisältämät kuvien osoitteet eivät toimi. Saat ne toimimaan laittamalla tutoriaalissa annetun oikean https-osoitteen ${this.baseUrl}-muuttujien paikalle. Kommentoi koodia tehdessäsi tutoriaalia, jotta ymmärrät kuinka sovellus toimii. Selvitä, millainen on sovelluksen komponenttien hierarkia, ja kuinka data virtaa valepalvelimelta komponentteihin. Voit kirjoittaa nämä ylös erilliseen tekstitiedostoon. Kun tutoriaali on tehty, toimii ja kuvat näkyvät, tee sovellukseen vielä seuraavat muutokset:
a) Tutoriaalissa sovelluksen TS-konfiguraatio, eli alkuasetukset (providers-taulukko ja siihen liittyvät importtaukset), on laitettu main.ts-tiedostoon. Laitetaan ne app.config.ts-tiedostoon, sillä TS-konfiguraation tulee olla siellä. Siirrä konfiguraatiotiedot main.ts:stä app.config.ts-tiedostoon, ja laita main.ts:ään viittaus app.config.ts:ään. Voit katsoa mallia uudesta Angular-projektista.
b) Käytä kiinteistöjen listauksen templaattisyntaksissa *ngFor-direktiivin sijasta @for-kontrollirakennetta, joka on pitkissä listauksissa suorituskyvyltään parempi ja siksi suositeltavampi.
c) Sovelluksessa käytetään tiedon hakemiseen valepalvelimelta, eli tässä tapauksessa JSON-serverin tarjoilemasta JSON-tiedostosta, fetch()-metodia ja promisea. Kommentoi tiedon hakemiseen liittyvä koodi ja korvaa se uudella koodilla, jossa käytät tiedon hakemiseen Angularin HttpClientia ja observablea. Huomaa että provideHttpClient, pitää laittaa app.config.ts:n providers-taulukkoon. Mallia saat tästä esimerkistä.
d) Sovelluksen hakulomake, jolla haetaan kiinteistöjä, ei ole reaktiivinen. Miksi ei ole? Tee lomakkeesta reaktiivinen Angularin signaalien avulla. Katso mallia tämän sovelluksen contactlist-komponentista. Sovellukseen palvelimelta tuleva olioita sisältävä taulukko muunnetaan observablesta signaaliksi, minkä jälkeen taulukkoa voidaan käsitellä signaalina, johon voi tehdä varsin helposti reaktiivisia hakuja.
Esimerkkinä esitetty ang-ristinolla -peli on jäänyt hieman keskeneräiseksi. Tee siihen seuraavat parannukset:
Toteuta Angularilla alla olevassa videossa kuvattu sovellus, jossa on toteutettu frontend-puolen autentikaatio, eli kirjautuminen tunnareilla näkymään, johon ei muuten ole pääsyä. Huomaa että backend-koodia ei ole, joten autentikaatio ei ole kokonaan toimiva. Sovelluksen nimeksi voit antaa vaikkapa "ang-regapp", sillä kyseessä on ilmoittautumissovellus. ng new ang-regapp --minimal -t=false -s=false.
Sovelluksessa on ylinnä navigaatio-komponentti (navbar), jossa ovat linkit muihin komponentteihin. Sovelluksen reitit vievät kolmeen eri komponenttiin: 1) Ilmoittautuneet (reglist) joka esittää listan ilmoittautuneista, 2) Ilmoittautumislomake (regform), eli Angularin form, jolla ilmoittaudutaan (Form-esimerkki), 3) Kirjautumislomake (loginform), jolla kirjaudutaan ilmoittautumislomakkeelle. Ilmoittautumislomake on suojattu Guard -providerilla (Guard -esimerkki). Huomaa, että Guardin voi edelleen toteuttaa vanhaan tapaan luokkana (deprecated, eli vanhentunut mutta toimii), mutta nykyään Guardit ovat funktioita, kuten yllä olevassa esimerkissä.
Sovelluksen tyylit on videossa tehty Bootstrapilla (Bootstrapkoe.html,Bootstrap-esimerkki), joten käytä sitä. Tee ilmoittautumislomakkeelle validaatio (Form-esimerkki), joka estää väärän muotoisen tiedon syöttämisen. Tee kirjautumislomakkeelle ainoastaan ilmoitus siitä, että kirjautuminen epäonnistui jos tunnus tai salasana olivat vääriä.
Käytä sovelluksessa tätä in-memory-data-service.ts -valetietokantaa (voit halutessasi tehdä muutoksia). Hae valetietokannassa olevat tunnarit servicen (nimi voi olla authservice) välityksellä loginform-komponentissa sijaitseviin muuttujiin, joihin vertaat käyttäjän antamia tunnareita. Jos ne ovat samat, eli kirjautuminen onnistui, voidaan käyttäjä päästää ilmoittautumislomakkeelle.
Navigaatiopalkkiin pitää välittää tieto sitä onko käyttäjä kirjautunut, jotta sisäänkirjautuminen-linkki (login) voidaan vaihtaa uloskirjautuminen-linkiksi (logout). Tämä onnistuu, kun teet authserviceen muuttujan, jossa on kirjautumisen tila (true tai false) ja välität sen navigointipalkkiin. Huomaa että koko sovelluksella on kaksi tilaa: kirjautunut (login) ja ei kirjautunut (logout). Tätä koko sovelluksen tilaa säilytetään authservicessä, josta se voidaan välittää komponenteille.
Tehdään alkeellinen verkkokauppa, jossa on NgRx Signalstorella kehitetty tilanhallinta. Ota pohjaksi tämä sovellus, jonka teet valmiiksi. Cartstore.ts-tiedostossa on kommentit, joiden perusteella rakennat valmiiksi cartstoren ja sen metodit. Mallia voi katsoa productstoresta ja esim. tästä koodista.
Valmiin ratkaisun toimintaperiaate on seuraavanlainen: Kun lisäät tuotekomponentissa tuotteen ostoskoriin, tuotteen määrä ja kokonaishinta ostoskorissa kasvavat. Samoin tuotteiden kokonaismäärä navigointipalkissa ostoskori-linkin perässä kasvaa. Kun lisäät ja poistat tuotteita ostoskorissa, niiden määrät ja kokonaishinnat kasvavat tai pienevät ja samoin käy varastomäärälle tuotekomponentissa. Kun siirryt maksukomponenttiin, siellä näkyy korin sisältö ja kaikkien korin tuotteiden yhteissumma. Tuotekomponentin tila on productstoressa ja muut komponentit saavat tilansa cartstoresta.
Tee Angularilla videossa esitetty käyttöliittymä, jossa on käytössä useita erilaisia valmiita Material Design -komponentteja. Käyttöliittymän tyylien ei tarvitse olla samat kuin videolla, mutta komponenttien toiminnan ja sijoittelun(layout) pitäisi olla samanlaiset. Tehtävän tarkoituksena on vain valmiiden UI-komponenttien kokeilu, joten sovelluksessa ei tarvitse olla sovelluslogiikkaa. Jos tehtäisiin oikea sovellus, pitäisi sovelluslogiikka koodata komponenttien TS-luokkiin. Tehtävässä ei tarvitse koodata paljoakaan, vaan komponentit luodaan automaattisesti skematiikan avulla tai kopioidaan MD-esimerkeistä.
Ohje: Tee uusi Angular-projekti, joka voi olla nimeltään vaikkapa
"ang-materialcomponents". Asenna Angular Material komennolla: ng
add @angular/material. Luo sovelluksen perusrakenne, eli
layout ja navigaatio, navigaatio-skematiikan avulla komennolla: ng
generate @angular/material:navigation navigation.
Luontikomennossa navigaatiokomponentin nimeksi tulee siis
"navigation". Laita syntyneen navigaatiokomponentin tagi
app.component.html:ään ja poista sieltä kaikki muu. Laita
router-outlet navigaatiokomponentin HTML-osan <!-- add content
here --> -kommentin alle.
Tee sitten reititys ja kolme alasivukomponenttia, joita voit vaihtaa navigaatiopalkin linkeistä. Voit asetella alasivukomponentteihin UI-komponentteja vierekkäin esim. CSS-gridin avulla. Huomaa että monet MD-komponentit tarvitsevat toisia MD-komponentteja riippuvuuksina. Selaimen konsolin virheilmoituksesta näet jos komponentteja puuttuu. Tätä ongelmaa ei tule, jos teet globalmodules.ts-tiedoston, jonka importtaat tällä tavalla kaikkiin MD-komponentteja käyttäviin komponentteihin. Tämä ei kasvata valmiin sovelluksen kokoa, sillä buildauksessa mukaan tulevat vain ne MD-komponentit, joita on käytetty. Huomaa että kolmannen alasivun stepperi-komponentissa käytetään reaktiivista lomaketta, mikä vaatii ReactiveFormsModulen importtauksen.
➤Video ratkaisun toiminnasta jossa näkyvät vaadittavat UI-komponentit.
Toteuta Angularilla sovellus joka piirtää viivadiagrammia
reaaliajassa websocket-serverin lähettämästä datasta. Dataa
lähettävä websocket-serveri on valmiina tässä ja dataa
vastaanottava Angular-sovellus tässä.
Tämän Angular-sovelluksen päälle teet siis reaaliaikaista dataa
esittävän viivadiagrammin eli line chartin. Voit käyttää chart.js
-kirjastoa, Angular-ohje on tässä. Kun importtaat
chart.js:n komponenttiin, käytä lausetta: import Chart from 'chart.js/auto'.
Vihje: homma hoituu siten, että subscribella komponenttiin saatu reaaliaikainen data muunnetaan Number -muotoon ja pushataan chartin datasets-taulukossa olevaan data-taulukkoon. Ohje: Updating charts. Labels -taulukossa olevaa x-akselin asteikkoa voi samanaikaisesti kasvattaa loppupäästä niin diagrammin esitys voi jatkua "loputtomasti". Voit tehdä esim. updateChart(realtimedata) -metodin jota kutsut subscriben sisällä. Tässä malli kutsusta.
Lopputyötä ei tarvitse välttämättä tehdä Angularilla, mikäli hallitset jonkin muun frontend-sovelluskehyksen/kirjaston peruskäytön. Lopputyössä täytyy kuitenkin esiintyä niitä frontend-sovelluksen piirteitä, joita on käsitelty tällä kurssilla. Niitä ovat esimerkiksi sovelluksen sisäinen reititys, datan siirto komponenttien välillä, sovelluksen sisäiset lomakkeet ja jonkinlainen arkkitehtuuri, kuten komponenttien yhteiset palvelut servicen avulla, sekä mahdollisesti (ei välttämätöntä) ulkoasukirjastojen (MD tai Bootstrap) käyttö, asynkronisen datan vastaanotto sovelluksen ulkopuolelta ja tilanhallinta. On erittäin suositeltavaa, että käyttäisit Typescriptiä. Lähes kaikkien frontend-kirjastojen kanssa voi nykyään käyttää TS:ää. Jos lopputyössä ei käytetä TS:ää, se huomioidaan arvioinnissa arvosanaa alentavana tekijänä.
Tee siis vapaamuotoinen frontend-projekti, jonka voit kehitellä täysin itse, tai webistä löytämäsi tutoriaalin pohjalta. Tyypillisin lopputyön aihe on CRUD-sovellus, jossa data on valetietokannassa (in-memory-web-api tai JSON-server). Tässä on esimerkki CRUD-sovelluksesta. Voit tehdä myös vaikkapa yksinkertaisen pelin (googlaa "Angular/React/Svelte game tutorial") ja kehittää peliin itse uusia ominaisuuksia. Esim. muistipeli tai ruudukkoon perustuva lautapeli olisivat hyviä aiheita. Joulukalenteri voisi olla hyvä aihe. Joulukalenterin arkkitehtuuri vaatii, että 24 luukkua pitää toteuttaa yhdellä komponentilla, jonka sisältö vaihtuu eli tila muuttuu.
Lopputyössä voisit yrittää perehtyä sellaisiin frontend-sovelluksen piirteisiin, joita ei ole kurssilla ehditty paljonkaan käsitellä. Esim. Angularin tapauksessa näitä voisivat olla MD-komponentit (kts. ang-materialdemo -esimerkki), animaatiot, signaalien hyödyntäminen (kts. signaaliesimerkit), tilanhallinta (kts. tilanhallintaesimerkit) tai server-side rendering.
Jos käytät lopputyösi pohjana tutoriaalia, laajenna tutoriaalin sovellusta kehittämällä siihen jotain uutta/omaa. Kommentoi tekstitiedostoon mitä uutta opit tehdessäsi tämän projektin.
Huomaa, että käyttäessäsi Typescriptiä, monien pienempien JS-kirjastojen käyttö vaatii yleensä @types/ -alkuisen tyyppimäärityksen, joka pitää asentaa erikseen, esim. @types/regression, mikäli käytät regression-js -kirjastoa. Lisäksi serviceen tai komponettiin importattava muuttuja saattaa Typescriptissä olla eri niminen kuin JS-ohjeessa. @types-tiedostosta näet minkä nimisiä muuttujia voit importata.
Lopuksi täytä kurssipalaute Peppi-järjestelmässä. Kurssilta ei voi saada arvosanaa, ennen kuin kurssipalaute on annettu.