Implementation
Angular 17+
angular-countries-flags
Standalone component with ControlValueAccessor support
for template-driven and reactive forms.
Try it live
Open the Angular demo page to try the component.
Styling examples
Go to the Angular styling section for Tailwind, Bootstrap, Angular Material, inline styles, and the slot map.
Installation
pnpm add @drobinetm/angular-countries-flags flag-icons
Load flag-icons in your angular.json styles array
or import it in your global stylesheet:
/* styles.css or angular.json styles[] */
@import 'flag-icons/css/flag-icons.min.css'; Basic usage
Import the standalone component and use it:
// app.component.ts
import { Component } from '@angular/core'
import { CountriesFlagsComponent } from '@drobinetm/angular-countries-flags'
import { FormsModule } from '@angular/forms'
@Component({
selector: 'app-root',
standalone: true,
imports: [CountriesFlagsComponent, FormsModule],
template: `
<drm-countries-flags
[(ngModel)]="selectedCode"
placeholder="Select a country"
/>
<p>Selected: {{ selectedCode }}</p>
`,
})
export class AppComponent {
selectedCode: string | null = null
} Reactive forms
The component implements ControlValueAccessor, so it
works with reactive forms.
import { Component } from '@angular/core'
import { FormControl, ReactiveFormsModule } from '@angular/forms'
import { CountriesFlagsComponent } from '@drobinetm/angular-countries-flags'
@Component({
standalone: true,
imports: [CountriesFlagsComponent, ReactiveFormsModule],
template: `
<drm-countries-flags [formControl]="countryControl" />
`,
})
export class MyComponent {
countryControl = new FormControl<string | null>(null)
} Filter & limit countries
<drm-countries-flags
[(ngModel)]="code"
[filter]="['es', 'us', 'br', 'ar', 'mx', 'co']"
[max]="20"
placeholder="Latin America + US + Spain"
/> Change event
import { CountryChangeEvent } from '@drobinetm/angular-countries-flags'
<drm-countries-flags
[(ngModel)]="code"
(valueChange)="onCountryChange($event)"
/>
onCountryChange(event: CountryChangeEvent) {
console.log(event.code) // 'es'
console.log(event.country) // { code: 'es', name: 'Spain' }
} CSS integrations
In Angular, you can style the component with utility classes, CSS frameworks, or inline style objects. The examples below are Angular-specific.
Tailwind works well in Angular when you disable the bundled styles
with unstyled.
<drm-countries-flags
[(ngModel)]="selectedCode"
[unstyled]="true"
[classNames]="{
root: 'w-full',
trigger:
'flex h-11 w-full items-center justify-between rounded-xl border border-slate-300 bg-white px-3 text-left text-slate-900 shadow-sm transition focus:outline-none focus:ring-2 focus:ring-sky-500',
triggerContent: 'flex min-w-0 items-center gap-2',
placeholder: 'text-slate-400',
label: 'truncate',
list: 'mt-2 max-h-64 overflow-auto rounded-xl border border-slate-200 bg-white p-1 shadow-2xl',
option: 'flex cursor-pointer items-center gap-2 rounded-lg px-3 py-2 text-sm',
optionActive: 'bg-slate-100',
optionSelected: 'bg-sky-600 text-white',
optionName: 'truncate'
}"
[styles]="{
flag: { borderRadius: '9999px' }
}"
></drm-countries-flags> You can also use Bootstrap utilities through the exposed slot classes.
<drm-countries-flags
[(ngModel)]="selectedCode"
[unstyled]="true"
[classNames]="{
root: 'w-100',
trigger: 'btn btn-outline-secondary w-100 d-flex align-items-center justify-content-between rounded-3 px-3 py-2',
triggerContent: 'd-flex align-items-center gap-2 text-truncate',
placeholder: 'text-secondary',
list: 'mt-2 list-unstyled border rounded-3 bg-body shadow-lg p-1',
option: 'd-flex align-items-center gap-2 rounded-3 px-3 py-2',
optionActive: 'bg-light',
optionSelected: 'bg-primary text-white',
optionName: 'text-truncate'
}"
[styles]="{
root: { minWidth: '280px' },
flag: { borderRadius: '50%' }
}"
></drm-countries-flags> The component is not a native Angular Material form field, but you can match it to Material layouts and surfaces.
// app.component.ts
import { Component } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { MatCardModule } from '@angular/material/card'
import { CountriesFlagsComponent } from '@drobinetm/angular-countries-flags'
@Component({
standalone: true,
imports: [FormsModule, MatCardModule, CountriesFlagsComponent],
template: `
<mat-card appearance="outlined">
<mat-card-content>
<drm-countries-flags
[(ngModel)]="selectedCode"
[unstyled]="true"
[classNames]="{
root: 'w-full',
trigger: 'mat-mdc-button-base w-full d-flex align-items-center justify-content-between px-3 py-3 rounded-4 border',
triggerContent: 'd-flex align-items-center gap-2 text-truncate',
placeholder: 'mat-body-medium text-medium-emphasis',
list: 'mt-2 rounded-4 border bg-surface p-1 mat-elevation-z8',
option: 'd-flex align-items-center gap-2 rounded-3 px-3 py-2',
optionActive: 'bg-light',
optionSelected: 'bg-primary text-white'
}"
[styles]="{
flag: { borderRadius: '9999px' }
}"
></drm-countries-flags>
</mat-card-content>
</mat-card>
`,
})
export class AppComponent {
selectedCode: string | null = null
}
If your project computes styles in TypeScript, bind them with the
styles input.
<drm-countries-flags
[(ngModel)]="selectedCode"
[unstyled]="true"
[styles]="{
root: { width: '100%', minWidth: '280px' },
trigger: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
width: '100%',
minHeight: '44px',
padding: '0 14px',
border: '1px solid #d4d4d8',
borderRadius: '16px',
backgroundColor: '#ffffff',
color: '#111827'
},
triggerContent: { display: 'flex', alignItems: 'center', gap: '8px', minWidth: 0 },
placeholder: { color: '#6b7280' },
list: {
marginTop: '8px',
padding: '6px',
listStyle: 'none',
border: '1px solid #e5e7eb',
borderRadius: '16px',
backgroundColor: '#ffffff',
boxShadow: '0 24px 48px rgba(15, 23, 42, 0.18)'
},
option: { display: 'flex', alignItems: 'center', gap: '8px', padding: '10px 12px', borderRadius: '12px' },
optionActive: { backgroundColor: '#f3f4f6' },
optionSelected: { backgroundColor: '#2563eb', color: '#ffffff' },
flag: { borderRadius: '9999px' }
}"
></drm-countries-flags> Props / Inputs
| Input | Type | Default | Description |
|---|---|---|---|
max | number | 0 | Max countries shown. 0 = unlimited. |
filter | string[] | [] | ISO alpha-2 whitelist. Empty = all. |
placeholder | string | "Select a country" | Trigger placeholder text. |
disabled | boolean | false | Disables the component. |
unstyled | boolean | false | Turns off the bundled UI styles. |
classNames | CountriesFlagsClassNames | {} | Classes by component slot. |
styles | CountriesFlagsStyles | {} | Inline styles by component slot. |
(valueChange) | CountryChangeEvent | — | Emits { country, code }. |