I en enkel eksempel kan vi se hvordan metoder som getRace() eller getRaces() kan spores i nettleserloggene når de blir kalt:

typescript
raceService.getRaces(); // logger: call to getRaces raceService.getRace(1); // logger: call to getRace

Når vi ser på hva en dekoratør i Angular faktisk er, ser vi at dekoratører er spesifikasjoner som brukes til å merke klasser, metoder eller egenskaper. De er en måte å legge til metadata på, slik at Angular kan forstå hvordan den skal håndtere klassen eller komponenten. Eksempelet nedenfor viser hvordan en dekoratør kan brukes på en komponent:

typescript
@Component({ selector: 'ns-home', template: 'home' }) class Home { constructor() { logger.log('Home'); } }

I dette tilfellet blir @Component-dekoratøren lagt til klassen Home, og Angular vil forstå at Home er en komponent når appen lastes inn, basert på metadataen som dekoratøren legger til. Dekoratører kan ta inn parametere, som i dette tilfellet er et konfigurasjonsobjekt. Dette er bare en introduksjon til dekoratører, og vi vil senere se på alle tilgjengelige dekoratører i Angular.

For de som er kjent med TypeScript, vil det være tydelig at Angular og alt verktøy rundt det er designet for TypeScript. Det er derfor det er anbefalt å bruke TypeScript til å utvikle applikasjoner i Angular, da det gir deg et sterkt typesystem som kan hjelpe deg å unngå mange vanlige feil.


Videre i TypeScript, kan vi utforske flere avanserte funksjoner som kan forbedre kvaliteten på koden din. En av de mest nyttige funksjonene i TypeScript er readonly. Denne kan brukes til å merke en egenskap av en klasse eller et grensesnitt som kun kan leses og ikke kan endres etter at objektet er opprettet:

typescript
interface Config { readonly timeout: number; }
const config: Config = { timeout: 2000 };
// `config.timeout` kan ikke endres senere i koden

En annen kraftig funksjon i TypeScript er keyof. Dette gjør at du kan hente en type som representerer en union av navngitte egenskaper fra et annet typeobjekt:

typescript
interface PonyModel { name: string; color: string; speed: number; }
type PonyModelKey = keyof PonyModel; // 'name' | 'color' | 'speed'

Dette gjør det mulig å bygge mer robuste funksjoner som kan hente verdier på en type-sikker måte, som i følgende eksempel:

typescript
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; }

Ved å bruke keyof kan vi forsikre oss om at koden vår er trygg, og at vi kun henter eksisterende egenskaper fra et objekt.

Når vi skal jobbe med typer som kanskje er delvis tilgjengelige, eller der vi ønsker å gjøre enkelte egenskaper valgfrie, kan vi bruke mapperte typer i TypeScript. For eksempel kan vi lage en type der alle egenskapene til PonyModel blir valgfrie:

typescript
type PartialPonyModel = {
[P in keyof PonyModel]?: PonyModel[P]; };

Denne typen transformerer alle egenskaper i et objekt til valgfrie, og TypeScript gir deg den nødvendige typebeskyttelsen.


TypeScript tilbyr også kraftige verktøy for å arbeide med unionstyper og typevakter, som gjør at vi kan håndtere forskjellige objekttyper på en effektiv og sikker måte. Anta at vi har to typer brukere, en autentisert bruker og en anonym bruker:

typescript
interface User { type: 'authenticated' | 'anonymous'; name: string; }
interface AuthenticatedUser extends User {
type: 'authenticated'; loggedSince: number; } interface AnonymousUser extends User { type: 'anonymous'; visitingSince: number; }

Her kan vi bruke en typevakt for å hjelpe TypeScript med å forstå hvilken type bruker vi har med å gjøre:

typescript
function isAuthenticated(user: User): user is AuthenticatedUser {
return user.type === 'authenticated'; } function isAnonymous(user: User): user is AnonymousUser { return user.type === 'anonymous'; }

Når vi bruker typevakter på denne måten, kan vi skrive mer presis kode som gjør det lettere å forstå og vedlikeholde. TypeScript kan automatisk oppdage hvilken type et objekt har basert på logikken vi skriver, og dette gjør at vi kan håndtere flere tilfeller på en trygg og effektiv måte.


Det er også viktig å forstå hvordan TypeScript håndterer unionstyper. Når man kombinerer flere typer sammen, kan TypeScript automatisk utlede hvilken type objektet har på forskjellige punkter i koden. Dette betyr at vi kan bruke unionstyper på en måte som gjør koden mer robust og forutsigbar. Når vi vet at modellen vår kan utvikles i fremtiden, er det viktig å ha i bakhodet at nye tilfeller kan trenge håndtering. TypeScript hjelper oss her ved å sikre at alle mulige tilfeller er dekket gjennom typeinferring.

Endtext

Hvordan velge riktig strategi for stilkapsling i Angular

I Angular finnes det flere måter å håndtere stilkapsling på. En av de viktigste beslutningene utviklere må ta er hvordan de skal sikre at stilene som defineres i komponentene, ikke påvirker eller blir påvirket av andre deler av applikasjonen. Denne utfordringen kan løses ved hjelp av ulike strategier for stilkapsling, som hver har sine egne fordeler og ulemper.

Den første strategien som ofte blir diskutert, er Shadow DOM-strategien. Denne strategien oppretter et skjult DOM-trær inne i komponenten, hvor stilene og strukturen er helt isolert fra resten av applikasjonen. Dette kan være nyttig i tilfeller der du ønsker å unngå at stiler "bløder" (det vil si, at de påvirker andre deler av applikasjonen) eller for å implementere spesifikke stilteknikker som kun skal gjelde for en komponent. Shadow DOM er imidlertid en relativt ny spesifikasjon og er derfor ikke støttet i alle nettlesere. Det er viktig å sjekke tilgjengeligheten av denne teknologien på nettsteder som caniuse.com før du bruker den i produksjon.

I tilfeller der Shadow DOM ikke er et alternativ, eller der du ønsker en mer kompatibel løsning, kan du bruke den emulerte strategien. Denne er standardinnstillingen i Angular og tilbyr en enklere løsning for stilkapsling. Den etterligner Shadow DOM, men uten å bruke selve Shadow DOM-teknologien. Istedenfor å bruke et skjult DOM, injiseres stilene direkte i komponentens HTML, og CSS-velgerne får et unikt attributt som gjør at stilene kun gjelder for komponenten og ikke for barnenelementer. Dette gir samme kapslingseffekt, men på en måte som er mer kompatibel på tvers av nettlesere.

En annen strategi som noen ganger benyttes, er None-strategien. Denne løsningen kapsler ikke stilene i det hele tatt, og lar dem flyte fritt gjennom applikasjonen. Dette betyr at stilene kan påvirke barnenelementer og komponenter, akkurat som vanlige globale CSS-regler. Denne strategien kan være nyttig i applikasjoner hvor du ikke trenger strengt stilkapsling, men det er viktig å være klar over at det kan føre til uforutsette problemer når komponentene blir mer komplekse.

I Angular kan du også style vertselementet i en komponent. Dette kan gjøres med den spesifikke CSS-velgeren :host. Denne velgeren lar deg style vertselementet for komponenten, enten du bruker Shadow DOM eller den emulerte strategien. Når du bruker Shadow DOM, forblir :host som det er, mens den blir omskrevet til et unikt attributt med den emulerte strategien.

Uavhengig av hvilken strategi du velger, er det viktig å forstå at Angular gjør det relativt enkelt å kapsle stilene dine. Den emulerte strategien tar seg av det meste av arbeidene for deg, og du kan enkelt bytte til Shadow DOM for spesifikke nettlesere, eller bruke None-strategien dersom du ønsker å unngå kapsling helt. Du kan til og med konfigurere strategien på komponentnivå, eller globalt i applikasjonens rotmodul.

Det er også viktig å merke seg at mens stilkapsling kan være nyttig for å unngå kollisjoner og uventet oppførsel, kan det i noen tilfeller føre til at stiler ikke virker som forventet, spesielt når du jobber med tredjepartsbiblioteker eller eldre nettlesere. Derfor bør du alltid teste applikasjonen grundig og vurdere hvilke strategier som passer best for ditt spesifikke brukstilfelle.

I tillegg til dette, bør du ha en klar forståelse av hvordan stiler påvirker ytelsen i applikasjonen din. Det er viktig å ikke bare fokusere på stilkapsling, men også hvordan du organiserer og optimerer CSS, slik at applikasjonen din er både rask og lett å vedlikeholde.

Hvordan effektivt internasjonalisere Angular-applikasjoner: Fra lokaliserte verdier til oversettelser

Når du bygger en applikasjon som skal støtte flere språk, er det viktig å forstå hvordan man håndterer både standardinnstillinger som valuta og språk, samt hvordan man oversetter tekst i applikasjonen. I Angular kan dette gjøres på en effektiv måte gjennom ulike verktøy og teknikker som gjør applikasjonen både fleksibel og rask, samtidig som den gir brukerne en sømløs opplevelse på sitt eget språk.

En enkel måte å begynne med internasjonalisering på i Angular er å sette en standard lokalitet, som for eksempel fransk (fr-FR) eller tysk (de-DE). Dette kan gjøres ved å injisere den ønskede lokaliteten via LOCALE_ID i applikasjonens bootstrap-prosess. Ved å bruke Angular 9 og senere versjoner, er det blitt enklere å konfigurere standardvaluta for hele applikasjonen ved å bruke DEFAULT_CURRENCY_CODE. Dette gjør at man unngår behovet for å spesifisere valuta hver gang, og setter i stedet en global standard for applikasjonen. For eksempel, ved å sette DEFAULT_CURRENCY_CODE til 'EUR', kan man bruke valutapipes uten å måtte spesifisere EUR hver gang.

Når det gjelder oversettelse av tekst, gir Angular i versjon 9.0 og videre, en helt ny tilnærming til internasjonalisering. Tidligere var det nødvendig å bruke eksterne biblioteker som angular-translate for å håndtere oversettelser dynamisk på klientsiden. I den nye løsningen bruker Angular en kompileringstid-basert strategi som forvandler oversettelser til del av den statiske applikasjonen allerede under byggingen. Dette betyr at applikasjonen må bygges på nytt for å endre språk, men den blir samtidig mye raskere ved at oversettelsene ikke trenger å lastes dynamisk under kjøring. Fordelen med denne tilnærmingen er at applikasjonen blir optimalisert for ytelse, og at oversettelsene er en integrert del av byggprosessen.

Prosessen for å internasjonalisere en applikasjon i Angular er delt inn i noen enkle trinn. Først markerer man de tekstene som skal oversettes i HTML-malene ved å bruke i18n-attributtet. Deretter bruker man verktøyet ng extract-i18n for å trekke ut de markerte tekstene til en fil, for eksempel messages.xlf, som inneholder de originale tekstene. Deretter kan en oversetter lage en oversatt versjon av filen, for eksempel messages.fr.xlf for fransk. Når filene er på plass, kan man bygge applikasjonen med lokalitets-IDen for ønsket språk, og Angular vil automatisk erstatte de markerte delene med de oversatte tekstene.

Et viktig aspekt ved denne prosessen er å forstå at når oversettelsen skjer på kompileringstid, kan man ikke endre oversettelsene uten å bygge applikasjonen på nytt. Dette betyr at språkbytter på klientsiden ikke er støttet dynamisk, noe som kan være en ulempe i noen scenarier. Men ved å bruke Ahead-of-Time (AOT) kompilering får man den fordelen at applikasjonen blir raskere, og at oversettelsene er en del av selve applikasjonen fra starten av.

Det er også viktig å merke seg at Angulars nye @angular/localize-pakke har gjort internasjonaliseringen enklere og mer integrert. Denne pakken gjør det mulig å bruke $localize-funksjonen for å oversette meldinger direkte i koden, og sikrer at oversettelsene er en del av byggprosessen. Når man bruker Angular CLI, er det veldig enkelt å legge til denne pakken med kommandoen ng add @angular/localize, og det gir en strømlinjeformet prosess for håndtering av oversettelser i applikasjonen.

Når du merker tekstene som skal oversettes, kan det være lurt å være oppmerksom på hvordan du strukturerer innholdet. For eksempel, tekst med variabler som {user.firstName} bør markeres på en måte som gjør det klart hvordan den skal oversettes. Dette kan også innebære å håndtere tekst i HTML-attributter, noe som gir en utfordring ved at enkelte deler av teksten kan være knyttet til spesifikke kontekster eller elementer.

I tillegg til de tekniske aspektene ved internasjonalisering, er det flere andre faktorer som kan påvirke hvordan oversettelser håndteres i applikasjoner. For eksempel bør du vurdere kulturelle forskjeller som kan påvirke hvordan informasjon presenteres på forskjellige språk. Dette kan inkludere alt fra datoformater og tidsformater til spesifikke farger eller symboler som kan ha ulik betydning i forskjellige kulturer. Det er også viktig å ta hensyn til hvordan applikasjonen håndterer tekst på språk med forskjellige retninger, som arabisk eller hebraisk, som kan kreve spesielle tilpasninger.

En annen viktig vurdering er hvordan man skal håndtere språkvalg og brukertilpassede innstillinger. I mange applikasjoner kan brukeren selv velge sitt språk, og det er viktig å sørge for at applikasjonen tilbyr et lettfattelig grensesnitt for dette. I tillegg bør man tenke på hvordan applikasjonen håndterer språkvalget, slik at brukeren kan endre språket uten at det skaper forvirring eller hindrer funksjonaliteten til applikasjonen.

Hvordan zoneless endringdeteksjon og renere kode kan forbedre ytelsen i Angular-applikasjoner

I de senere versjonene av Angular har rammeverket gjort store fremskritt når det gjelder effektivitet og ytelse. En viktig forbedring er overgangen til zoneless endringdeteksjon, som ble introdusert fra og med versjon 18. Denne endringen er et stort steg mot å redusere kompleksiteten og forbedre ytelsen i Angular-applikasjoner, spesielt når applikasjonen begynner å vokse i størrelse og kompleksitet.

Zoneless endringdeteksjon betyr at Angular nå kan synkronisere applikasjonens tilstand med DOM uten å være avhengig av ZoneJS, som tidligere ble brukt til å håndtere asynkrone hendelser og oppdateringer. I stedet for å vente på at ZoneJS skal registrere endringer i applikasjonen, kan Angular selv avgjøre når en oppdatering må gjøres, basert på signalverdier og deres endringer. Denne metoden gjør applikasjonen mer responsiv og forenkler koden ved å fjerne et ekstra lag av kompleksitet.

Det finnes flere fordeler med denne tilnærmingen. Først og fremst får utviklere mer kontroll over når og hvordan endringer skjer. Tidligere var ZoneJS et obligatorisk verktøy for å oppnå korrekt synkronisering, men det kan nå fjernes helt fra applikasjonen. For å oppnå dette må utviklerne legge til en spesifikk innstilling i applikasjonens leverandørkonfigurasjon og fjerne avhengigheten til ZoneJS fra prosjektet, noe som vanligvis gjøres ved å modifisere angular.json-filen.

Men det er en viktig forutsetning: både applikasjonens egen kode og alle eksterne Angular-biblioteker som benyttes må være forberedt på zoneless endringdeteksjon. Dette innebærer at alle komponenter må bruke signaler (eller den asynkrone pipen) for å håndtere tilstanden, og at koden ikke bør bruke eldre metoder som NgZone.onStable.

En annen viktig ytelsesforbedring i Angular er bruken av "pure pipes". En pipe er et verktøy som lar utviklere transformere data i Angulars maler, som for eksempel å vise et fullt navn basert på brukerens fornavn, etternavn og tittel. Vanligvis kan dette gjøres på to måter: ved å skrive en metode i komponenten eller ved å definere en pipe som kan gjenbrukes i ulike maler.

Når du bruker en pipe, får du en betydelig ytelsesfordel, fordi Angular optimaliserer pipe-funksjonene ved å memorere resultatene. Denne mekanismen betyr at transform-metoden i en pipe bare kalles når en av argumentene endres, på samme måte som Angular gjør med signaler i den nye zoneless endringdeteksjonen. Dette reduserer unødvendige beregninger og forbedrer appens responsivitet.

Men det er viktig å merke seg at pipe-funksjoner som er "pure" (eller rene), ikke alltid oppdateres hvis inngangsverdiene blir mutert. Hvis du endrer et objekt direkte, vil ikke pipe-funksjonen kjøres på nytt, med mindre objektets referanse endres. For å håndtere dette, kan utviklere velge å bruke immutable objekter, som aldri endres direkte, eller markere pipen som "impure" (utren), slik at den alltid kjøres når dataene oppdateres. Dette kan føre til et lite ytelsestap, men sikrer at visningen alltid er oppdatert.

En annen løsning for å unngå problemer med muterte objekter er å bruke signals for å holde på tilstandene i applikasjonen. Signals er designet for å gjøre det lettere å reagere på endringer i applikasjonens tilstand og tillater at komponenter kan "lytte" til disse endringene på en effektiv måte. Når signaler brukes sammen med onPush-strategien, oppnår man bedre ytelse, fordi Angular kun utfører endringdeteksjon når signalene endres.

De nevnte endringene er spesielt viktige når man begynner et nytt prosjekt. Å bygge applikasjoner med signaler og zoneless endringdeteksjon fra starten av gir utviklerne et solid grunnlag for å bygge svært effektive applikasjoner. Det er også viktig å merke seg at de fleste populære Angular-komponentbibliotekene har forberedt seg på denne overgangen, og mange av eksemplene i denne boken er allerede kompatible med zoneless-teknikken.

Det er imidlertid viktig å forstå at ytelsesoptimalisering aldri bør gjøres uten grundig testing og måling. Før man begynner å optimalisere, bør man alltid sikre seg at det faktisk er ytelsesproblemer som må løses. Prematur optimalisering kan ofte føre til unødvendig kompleksitet og feil. Det er viktig å først gjøre applikasjonen så enkel, korrekt og lesbar som mulig før man begynner å tenke på optimering, og kun ta skritt for å forbedre ytelsen etter at man har identifisert spesifikke flaskehalser.

Zoneless endringdeteksjon og bruk av signaler er fremtidens standard for Angular-applikasjoner, og gir en mer robust og effektiv utviklingsprosess. Men som med all teknologi, er det viktig å bruke disse verktøyene med omhu og forstå hvordan de påvirker applikasjonens arkitektur. Å benytte seg av disse teknikkene vil ikke bare forbedre applikasjonens ytelse, men også gjøre koden enklere å vedlikeholde på lang sikt.