I Angular er det et sett med kraftige verktøy, kjent som pipes, som lar deg transformere data direkte i malene (templates) uten å måtte endre på komponentlogikken. Disse pipes kan være utrolig nyttige når du trenger å formatere tekst, tall eller datoer, eller håndtere asynkrone data. I denne delen av boken skal vi utforske hvordan du kan bruke noen av de mest vanlige pipes, og hvordan du kan tilpasse dem til spesifikke behov i Angular-applikasjoner.

En av de mest grunnleggende pipes i Angular er keyvalue pipe, som brukes til å iterere gjennom objekter eller kart (maps) og vise nøkkel-verdi-par. Denne pipe gir en enkel og effektiv måte å vise dataene på i malene uten å måtte skrive kompleks logikk i komponentene.

For eksempel, når du har en liste med ponni-data, kan du bruke keyvalue pipe for å iterere gjennom et kart og vise navnene på hver ponni. La oss se på et eksempel:

typescript
@Component({ selector: 'ns-ponies', template: ` <div *ngFor="let entry of ponies() | keyvalue; trackBy: trackEntry"> {{ entry.key }} - {{ entry.value.name }} </div> `, imports: [KeyValuePipe] }) export class Ponies { protected readonly ponies = signal( new Map([ [103, { name: 'Rainbow Dash' }], [56, { name: 'Pinkie Pie' }] ]) ); }

I dette tilfellet bruker vi keyvalue pipe for å vise ponniens nøkkel (ID-en) og navn. Det er verdt å merke seg at hvis du har null- eller undefined-nøkler, vil de vises på slutten av listen. For mer kontroll kan du definere en egendefinert sammenligningsfunksjon (comparator) som styrer hvordan dataene skal sorteres.

typescript
@Component({ selector: 'ns-ponies', template: ` <div *ngFor="let entry of poniesWithScore() | keyvalue: ponyComparator; trackBy: trackEntry"> {{ entry.key.name }} - {{ entry.value }} </div> `, imports: [KeyValuePipe] }) export class Ponies { protected readonly poniesWithScore = signal( new Map([ [{ name: 'Rainbow Dash' }, 430], [{ name: 'Rainbow Dash' }, 680], [{ name: 'Pinkie Pie' }, 125] ]) ); ponyComparator(a: KeyValue, b: KeyValue): -1 | 0 | 1 { if (a.key.name === b.key.name) { return 0; } return a.key.name < b.key.name ? -1 : 1; } }

Denne tilnærmingen gir mer kontroll over hvordan objektene dine skal sorteres, og gir deg muligheten til å formatere visningen mer presist.

Når vi snakker om pipes, er det også viktig å nevne standardformatene for teksttransformasjon. Angular tilbyr flere innebygde pipes som gjør det enkelt å manipulere strenger, tall og valuta:

  • uppercase pipe konverterer tekst til store bokstaver.

  • lowercase pipe konverterer tekst til små bokstaver.

  • titlecase pipe setter den første bokstaven i hvert ord til stor bokstav.

For eksempel:

html
{{ 'Ninja Squad' | uppercase }} <!-- Resultat: 'NINJA SQUAD' --> {{ 'Ninja Squad' | lowercase }} <!-- Resultat: 'ninja squad' --> {{ 'ninja squad' | titlecase }} <!-- Resultat: 'Ninja Squad' -->

Men Angular tilbyr også flere avanserte pipes for internasjonalisering (i18n), som gjør det lettere å formatere tall, valuta og datoer i forskjellige kulturer. Dette er nyttig for applikasjoner som skal brukes globalt eller på tvers av forskjellige språk.

For eksempel kan number pipe brukes til å formatere tall med tusenskilletegn og desimaler. Du kan definere nøyaktig hvordan tallene skal vises, for eksempel med spesifikke krav for antall desimaler:

html
{{ 12345 | number }} <!-- Resultat: '12,345' --> {{ 12345 | number:'6.2' }} <!-- Resultat: '012,345.00' -->

percent pipe lar deg vise prosenter:

html
{{ 0.8 | percent }} <!-- Resultat: '80%' --> {{ 0.8 | percent:'.3' }} <!-- Resultat: '80.000%' -->

currency pipe formaterer beløp i en spesifisert valuta, for eksempel USD eller EUR:

html
{{ 10.6 | currency:'CAD' }} <!-- Resultat: 'CA$10.60' --> {{ 10.6 | currency:'USD':'symbol' }} <!-- Resultat: '$10.60' -->

For datoformatering brukes date pipe til å vise datoer i ulike formater, for eksempel:

html
{{ birthday() | date:'dd/MM/yyyy' }} <!-- Resultat: '25/12/2025' --> {{ birthday() | date:'shortDate' }} <!-- Resultat: '12/25/25' --> {{ birthday() | date:'longDate' }} <!-- Resultat: 'December 25, 2025' -->

En annen veldig nyttig pipe er async pipe, som håndterer asynkrone data (fra Promises eller Observables). Denne pipen er veldig praktisk når du henter data fra en ekstern API eller andre asynkrone kilder, da den sørger for at dataene blir riktig håndtert og oppdatert i brukergrensesnittet når de blir tilgjengelige.

html
{{ asyncGreeting | async }}

I eksemplet ovenfor brukes en Promise for å hente en hilsen, og når den er oppløst etter ett sekund, vises den i brukergrensesnittet.

Ved å bruke disse pipes kan du forenkle applikasjonens kode og unngå unødvendige endringer i komponentene dine. De gir også et fleksibelt og effektivt system for å tilpasse visningen av dataene etter spesifikasjoner som er relevante for ditt brukstilfelle.

Det er viktig å merke seg at bruken av pipes, særlig i store applikasjoner, kan ha en påvirkning på ytelsen hvis ikke brukt riktig. Overbruk av async pipe i kombinasjon med store datamengder kan føre til at det blir flere unødvendige abonnenter og oppdateringer. Derfor bør man alltid være bevisst på når og hvordan pipes anvendes, spesielt når det gjelder asynkrone datakilder.

Hvordan sikre effektiv validering og feilbehandling i skjemaer i Angular?

Validering utgjør en sentral del av skjemautvikling, og det handler om å sikre at brukerinndata tilfredsstiller visse krav før de sendes inn. Noen felt kan være obligatoriske, andre kan ha avhengigheter eller krav til format, eller begrensninger på verdier, som for eksempel at et tall ikke skal være lavere eller høyere enn en bestemt grense. Den grunnleggende tilnærmingen starter ofte med at alle feltene må fylles ut, altså er obligatoriske.

I kodebaserte skjemaer (code-driven forms) brukes validatorer for å sikre valideringsregler. En validator returnerer en feilstruktur hvis den finner feil, ellers null. Angular tilbyr flere innebygde validatorer, som Validators.required for obligatoriske felt, Validators.minLength og Validators.maxLength for å regulere lengden på tekst, Validators.email for å validere e-postadresser, samt Validators.min og Validators.max for numeriske begrensninger. Det er også mulig å bruke Validators.pattern for å validere mot regulære uttrykk.

Man kan kombinere flere validatorer i et array på både enkeltkontroller og grupper av kontroller. For eksempel kan man stille krav om at brukernavnet må være minst tre tegn, samtidig som det er påkrevd at passordfeltet ikke er tomt.

I skjemaer som drives via malbasert tilnærming (template-driven forms) legges valideringsregler til direkte i HTML ved hjelp av attributter som required, minlength, maxlength og email. Disse direktivene aktiverer automatisk validering, og min- og max-direktiver er foreløpig ikke tilgjengelige som standard.

Ved innsending av skjema er det avgjørende at brukeren ikke kan sende inn skjemaet dersom det inneholder feil. Det oppnås ved å binde submit-knappens disabled-egenskap til skjemaets gyldighetsstatus. Dersom skjemaet ikke er gyldig, blir knappen deaktivert.

For å gi brukeren god tilbakemelding må feilmeldinger vises tydelig og presist. I kodebaserte skjemaer kan man sjekke hver enkelt kontrolls feiltyper ved hjelp av metoder som hasError, kombinert med tilstand som dirty for å unngå at feilmeldinger vises før brukeren har forsøkt å fylle ut feltet. Dette gir en mer brukervennlig opplevelse, der feil ikke vises umiddelbart, men først når feltet er endret.

For å redusere gjentakelse og øke lesbarheten i koden, kan man opprette referanser til hver kontroll i komponenten, og bruke disse direkte i malen for å hente ut status og feil.

I malbaserte skjemaer finnes det ingen eksplisitte felt i komponenten som refererer til FormGroup, men man kan deklarere en lokal variabel i malen som refererer til NgForm-objektet. Dette gir tilgang til skjemaets tilstand og kontrollene det inneholder, og kan brukes på tilsvarende måte for å vise feil og deaktivere innsending.

Det er viktig å forstå at selv om Angular gir kraftige verktøy for validering og feilbehandling, krever god skjemadesign også vurdering av brukeropplevelse. Å vise feilmeldinger for tidlig kan virke forstyrrende, mens for sen tilbakemelding kan føre til frustrasjon når skjemaet avvises uten forklaring. Å finne balansen mellom valideringens strenghet, responsiv tilbakemelding og enkelhet i koden er avgjørende for å utvikle robuste, brukervennlige skjemaer.

I tillegg til teknisk validering bør man også ta høyde for tilgjengelighet og internasjonalisering, slik at feilmeldinger er klare, forståelige og tilgjengelige for alle brukere, uavhengig av funksjonsnedsettelser eller språk.