Adressesøk (address-autocomplete)¶
Gjenbrukbar, presentasjonell søkefelt-komponent for verdensomspennende sted-/firma-/
adressesøk via Google Places, bygget for docs/address-autocomplete/ADDRESS_AUTOCOMPLETE_PLAN.md.
Brukeren søker på et firmanavn (f.eks. «Bruusgaard AS»), et sted, eller en
gateadresse hvor som helst i verden. Ved valg av et treff løser komponenten hele
adressen og emitterer et parset resultat — verten (host) mapper feltene inn i sitt eget
skjema.
Komponenten er presentasjonell og skrivebeskyttet: den skriver aldri direkte til ePortal.
Google-oppslaget går gjennom en server-side proxy (GooglePlacesController, Slice S1) — Google-
API-nøkkelen når aldri nettleseren. Autocomplete er strengt additiv: manuell utfylling av
vertens egne felt fungerer alltid, uavhengig av om Google-søket er slått på for tenanten.
Status per Slice S2 (2026-07-18): komponenten, den rene parseren og toAlpha3()-hjelperen er
levert og enhetstestet. Den er ikke koblet inn i leveringsadresse-velgeren eller CRM-
adresseskjemaene ennå — det er planens Slice S3 (masterordre) og S4 (CRM), som per plan §14 også
må levere sin egen alpha-3-persistens-test (§6.4) uavhengig av rekkefølge.
Feature-tabell¶
| Komponent | Selector | Hovedfunksjon | Import |
|---|---|---|---|
| AddressAutocompleteComponent | app-address-autocomplete |
Debounced søkefelt mot Google Places (proxy), viser treff, løser full adresse ved valg og emitterer et parset resultat | Standalone |
Kildefiler¶
| Del | Sti |
|---|---|
| Komponent | ui/ePortal.ui/src/app/components/shared/address-autocomplete/address-autocomplete.component.ts |
| Mal | ui/ePortal.ui/src/app/components/shared/address-autocomplete/address-autocomplete.component.html |
| Ren parser | ui/ePortal.ui/src/app/components/shared/address-autocomplete/address-autocomplete.helpers.ts |
| Tester | address-autocomplete.component.spec.ts, address-autocomplete.helpers.spec.ts (samme mappe) |
| Frontend-klient mot proxyen | ui/ePortal.ui/src/app/services/google-places.service.ts |
| Modelltype | AutocompleteAddress i ui/ePortal.ui/src/app/shared/models.ts |
| Alpha-2 → alpha-3-hjelper | toAlpha3() i ui/ePortal.ui/src/app/components/shared/delivery-address-picker/delivery-address-picker.helpers.ts (mirror av eksisterende toAlpha2() — samlet ett sted for å unngå duplikat) |
| Backend-proxy (Slice S1) | api/ePortal.API/ePortal.API/Controllers/GooglePlacesController.cs — GET capability, POST autocomplete, POST details |
Komponenten er standalone — importer klassen direkte i vertens imports. Den bruker
ng-select (appendTo="body") for treff-nedtrekket, samme mønster som
leveringsadresse-velgeren og Brønnøysund-søket i CRM-kundeskjemaet.
Bruk¶
<app-address-autocomplete
[label]="'Module.searchAddressLabel' | translate"
(addressSelected)="onAutocomplete($event)"
(searchCleared)="onAutocompleteCleared()">
</app-address-autocomplete>
onAutocomplete(addr: AutocompleteAddress): void {
// Host maps the emitted fields into its own form — the component never writes anything itself.
this.manualDraft = {
...this.manualDraft,
name: addr.name ?? this.manualDraft.name,
line1: addr.line1,
line2: addr.line2,
postalCode: addr.postalCode,
city: addr.city,
countryCode: addr.countryCode // alpha-2 — convert with toAlpha3() for an alpha-3 column
};
}
Inputs¶
| Input | Type | Standard | Beskrivelse |
|---|---|---|---|
disabled |
boolean |
false |
Deaktiverer feltet (f.eks. mens verten lagrer). |
placeholder |
string \| null |
null |
Overstyrer standard-placeholder (AddressAutocomplete.searchPlaceholder). |
label |
string \| null |
null |
Valgfri feltetikett. Uten den brukes en usynlig (visually-hidden) etikett for skjermlesere. |
countryRestriction |
string[] \| null |
null |
Reservert for en fremtidig utvidelse — se «Kjente fallgruver» under. Har ingen effekt i dag, fordi S1-proxyens autocomplete-forespørsel ikke tar imot en landrestriksjon per kall (kun tenant-innstillingen Integrations.GooglePlaces.CountryRestriction, eksponert read-only via capability). |
Outputs¶
| Output | Type | Beskrivelse |
|---|---|---|
addressSelected |
EventEmitter<AutocompleteAddress> |
Emitteres én gang når brukeren velger et treff og Place Details er løst opp. |
searchCleared |
EventEmitter<void> |
Emitteres når feltet tømmes — lar verten nullstille avhengig UI. |
Modelltype¶
// shared/models.ts
interface AutocompleteAddress {
name: string | null; // firma-/stednavn — kun satt for et establishment-treff
line1: string | null; // "<gate> <husnummer>" i norsk rekkefølge
line2: string | null; // subpremise/etasje — aldri diktet opp
postalCode: string | null;
city: string | null; // postal_town -> locality -> sublocality, første tilstede
countryCode: string | null; // ISO 3166-1 alpha-2 (Google country.shortText)
latitude?: number | null;
longitude?: number | null;
placeId?: string | null; // reservert for fremtidig audit/dedupe
formattedAddress?: string | null; // Googles ferdigformaterte adresse — kun visning/debug
}
Oppførsel¶
- Debounced søk (~300 ms), min. 3 tegn før et Autocomplete-kall sendes — matcher
Brønnøysund-søket i CRM-kundeskjemaet (
initializeBrregTypeahead). - Kapabilitetssjekk ved oppstart: komponenten kaller
GET GooglePlaces/capabilityingOnInit. Til svaret kommer tilbake er feltet skjult (fail-safe). Resolver kapabilitetenenabled:false(funksjonen av eller uten nøkkel for tenanten), eller feiler kallet, rendres hele komponenten som ingenting — vertens vanlige manuelle felt er den eneste input-flaten. - Session-token: komponenten genererer ett token per søkesesjon (
crypto.randomUUID()), gjenbruker det på tvers av alle debounced Autocomplete-kall i samme søk, sender det med det ene Details-kallet ved valg, og nullstiller det etter et valg eller ved tømming — én ny Google-faktureringssesjon per faktiske søk (planens §4.3). - Delvis feil (ikke hard av): hvis et enkelt Autocomplete- eller Details-kall svarer
enabled:false(f.eks. kvote nådd) eller feiler nettverksmessig, vises en dempet «adressesøk utilgjengelig»-hint under feltet — komponenten skjules ikke, og manuell utfylling er upåvirket. - Ren parser:
parseGooglePlaceDetails()iaddress-autocomplete.helpers.tsmapper Google Place Details →AutocompleteAddressuten sideeffekter. Norske treff har ofte bådepostal_townoglocality—postal_townforetrekkes (feil by ellers for mange norske postnummerområder). - Land — ingen automatisk konvertering i komponenten:
countryCodeemitteres alpha-2 rett fra Google. Skriver verten inn i en alpha-3-kolonne (f.eks. CRM-adressekortetswv_ActorAdr.actaCountry char(3)), MÅ verten kalletoAlpha3()førpatchValue()—app-country-select.writeValue()løser kun opp for visning, den skriver aldri den normaliserte koden tilbake til skjemaets modellverdi. - Manuelt overstyr vinner alltid: alle felt forblir redigerbare etter et valg — søket bistår, det låser aldri et felt (planens §6.5).
i18n¶
Alle brukerrettede tekster ligger under AddressAutocomplete.* i både no.json og
en.json (blokken er en-speilet). Sentrale nøkler:
"AddressAutocomplete": {
"searchLabel": "Søk etter adresse, sted eller firma",
"searchPlaceholder": "Søk etter adresse, sted eller firma …",
"typeToSearchHint": "Skriv minst 3 tegn for å søke",
"poweredByGoogle": "Søket bruker Google Places",
"searchUnavailable": "Adressesøk er ikke tilgjengelig akkurat nå — skriv adressen manuelt"
}
Tilgjengelighet og mobil¶
ng-selectmedappendTo="body"— tastaturnavigasjon og søk som standard, klippes ikke av skuff-/modal-scrolling.- Uten en gitt
label-input rendres envisually-hiddenetikett for skjermlesere, ogng-selectfår[attr.aria-label]satt til samme tekst. - Den dempede «Google-powered»/«utilgjengelig»-hinten er ren tekst, ingen dekorativ farge som strider mot fargereglene i CLAUDE.md.
Kjente fallgruver¶
| Fallgruve | Riktig mønster |
|---|---|
Anta at countryRestriction-inputen faktisk begrenser søket |
Den er reservert for en fremtidig backend-utvidelse — S1-proxyens autocomplete-forespørsel tar i dag kun input/sessionToken. Kun tenant-innstillingen (Integrations.GooglePlaces.CountryRestriction) virker per nå. |
| La komponenten skrive direkte til et skjema | Den er ren/skrivebeskyttet — verten lytter på addressSelected og mapper feltene selv. |
Patch en alpha-3-kolonne med addr.countryCode uten konvertering |
countryCode er alltid alpha-2. Kall toAlpha3() (fra delivery-address-picker.helpers.ts) før patchValue() på en alpha-3-kontroll. |
| Stole på at Google-nøkkelen er tilgjengelig i nettleseren | Den er det aldri — alt går via GooglePlacesController-proxyen (Slice S1). |
| Vise komponenten uten kapabilitetssjekk | enabled starter som null (skjult) til capability-kallet svarer; ikke render feltet før det er avklart. |
Verifiseringspunkter¶
- Med
Integrations.GooglePlaces.Enabled = false(eller ingen nøkkel) for tenanten: importer komponenten på en testside — feltet skal ikke rendres i det hele tatt. - Med funksjonen slått på: søk på et firmanavn — treffene skal vise primær-/sekundærtekst;
velg et treff —
addressSelectedskal emitteres med parsede felt ogcountryCodealpha-2. - Skriv under 3 tegn — ingen nettverkskall skal utløses (
GooglePlacesService.autocompletekalles ikke). - Simuler et kvote-/feilsvar fra proxyen — feltet skal forbli synlig med en dempet «utilgjengelig»-hint, ikke skjules eller kaste en feil.
Relaterte sider¶
- Komponenter
- Land-velger (country-select)
- Leveringsadresse-velger (delivery-address-picker)
- Plan:
docs/address-autocomplete/ADDRESS_AUTOCOMPLETE_PLAN.md