Kopier-knapp (copy-btn)¶
Gjenbrukbar én-klikks kopier-knapp (ikonknapp) for identifikatorer og andre
korte tekstverdier. Skjuler seg selv når verdien er tom, kopierer via
navigator.clipboard med fallback til document.execCommand('copy'), og gir
tilbakemelding via toast. Bygget som delt infrastruktur (sub-prosjekt B) og
brukt første gang på CRM-kundekortet (se CRM-modulen),
men generell og kan gjenbrukes av enhver side som trenger en kopier-affordanse.
Feature-tabell¶
| Komponent | Selector | Hovedfunksjon | Import |
|---|---|---|---|
| CopyBtnComponent | app-copy-btn |
Kopier en tekstverdi til utklippstavlen med ett klikk; skjult når verdien er tom | Standalone og SharedModule |
Kildefiler¶
| Del | Sti |
|---|---|
| Komponent | ui/ePortal.ui/src/app/shared/components/copy-btn/copy-btn.component.ts |
| Tester | ui/ePortal.ui/src/app/shared/components/copy-btn/copy-btn.component.spec.ts |
| Eksport | ui/ePortal.ui/src/app/shared/shared.module.ts (importert og eksportert) |
Bruk¶
<!-- Ved siden av en verdi (badge, felt, sidebar-rad) -->
<span class="badge badge-soft-secondary">
{{ 'Crm.customerNo' | translate }}: {{ customer.customerNo }}
</span>
<app-copy-btn [value]="customer.customerNo" [label]="'Crm.customerNo' | translate"></app-copy-btn>
Komponenten er eksportert fra SharedModule, så feature-moduler som allerede
importerer SharedModule kan bruke den uten ekstra import.
Inputs¶
| Input | Type | Standard | Beskrivelse |
|---|---|---|---|
value |
string \| null \| undefined |
– | Teksten som skal kopieres. Når den er tom/blank etter .trim(), rendrer hele komponenten ingenting (ingen deaktivert spøkelsesknapp) — kalleren trenger ikke egen *ngIf. |
label |
string |
– | Menneskelig navn på feltet (allerede i18n-oversatt), brukt til å bygge standard aria-label via General.copyValue («Kopier {{value}}»). |
ariaLabel |
string |
– | Eksplisitt aria-label-overstyring (allerede i18n-oversatt). Vinner over den genererte standarden. |
Komponenten har ingen @Output().
Tilgjengelig etikett (obligatorisk)¶
Knappen rendres aldri uten aria-label. Rekkefølgen er:
ariaLabelhvis satt (brukes ordrett).- Ellers
label→General.copyValuemed{{value}}=label. - Ellers
General.copy(«Kopier»).
Send alltid i18n-oversatt tekst inn i label/ariaLabel — aldri hardkodet
norsk. Eksempel: [label]="'Crm.email' | translate".
Utklippstavle-fallback¶
navigator.clipboard.writeText(value)forsøkes først.- Hvis Clipboard API mangler (usikker kontekst) eller avvises (nektet
tilgang), faller komponenten tilbake til en skjult
<textarea>+document.execCommand('copy'). - Hvis også fallbacken feiler, vises en feil-toast (
General.copyFailed).
Ved suksess via en av banene vises suksess-toasten General.copied («Kopiert»)
og et kort avkryssingsikon på knappen. All tilbakemelding går via
ToastService.show(...) (ingen modal, ingen alert()).
i18n¶
Nøklene finnes i BÅDE no.json og en.json under General:
"General": {
"copy": "Kopier",
"copied": "Kopiert",
"copyValue": "Kopier {{value}}",
"copyFailed": "Kunne ikke kopiere"
}
Tilgjengelighet og mobil¶
- Alltid
aria-label(fallback-kjeden over) ogtitlemed samme tekst. - Ikon er
aria-hidden="true". stopPropagation()på klikk slik at en kopier-knapp inne i en klikkbar rad eller badge ikke også trigger rad-/badge-handlingen.
Kjente fallgruver¶
| Fallgruve | Riktig mønster |
|---|---|
| Hardkode norsk etikett i malen | Send i18n-oversatt tekst inn i [label]/[ariaLabel] (f.eks. [label]="'Crm.email' \| translate"). |
Pakke <app-copy-btn> i egen *ngIf på verdien |
Unødvendig — komponenten skjuler seg selv på tom verdi. |
| Legge kopier-knapp på telefon/mobil | I CRM-kundekortet er telefon/mobil bevisst kun tel:-ikoner; kopier er kun på identifikatorer og e-post (låst beslutning). |
Egen copyValue()-metode per komponent |
Bruk app-copy-btn — den er den delte kopier-affordansen. |