Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Country Code Field Laravel Package

tapp/filament-country-code-field

A country code select form field, table column, and table filter for Laravel Filament. Easily add searchable country codes to your resources' forms and tables, with a publishable config file. Supports Filament 4.x and 5.x.

View on GitHub
Deep Wiki
Context7

Getting Started

Match the version to your Filament major first — this is the single most important install step:

Filament Package
4.x / 5.x ^2.0 (use ^2.1.1, see gotchas)
3.x ^1.0
composer require tapp/filament-country-code-field:"^2.0"

# optional but recommended — inspect what's configurable before you build on it
php artisan vendor:publish --tag="filament-country-code-field-config"

There is no npm build step and no panel plugin registration — the three classes are plain Filament components you drop into a schema.

Where to look first:

  1. The published config file — it's the country list / locale source of truth. Confirm which codes (ISO 3166-1 alpha-2, presumably) and which casing it produces before you design a column around it.
  2. vendor/tapp/filament-country-code-field/src/Forms/Components/CountryCodeSelect.php — it extends the native Filament Select, so everything you know about Select (->searchable(), ->preload(), ->options()) applies. Reading the class takes two minutes and answers 90% of "can it do X".
  3. CHANGELOG / releases — the package is small (21 stars, 0 dependents) and fixes are surgical; the release notes are the best bug tracker.

First use case — a customer/lead record with an international phone or address:

use Tapp\FilamentCountryCodeField\Forms\Components\CountryCodeSelect;
use Tapp\FilamentCountryCodeField\Tables\Columns\CountryCodeColumn;
use Tapp\FilamentCountryCodeField\Tables\Filters\CountryCodeSelectFilter;

public static function form(Form $form): Form
{
    return $form->schema([
        CountryCodeSelect::make('country_code')
            ->default('us')
            ->required(),
        TextInput::make('phone')->tel(),
    ]);
}

public static function table(Table $table): Table
{
    return $table
        ->columns([
            CountryCodeColumn::make('country_code'),
            TextColumn::make('phone'),
        ])
        ->filters([
            CountryCodeSelectFilter::make('country_code'),
        ]);
}

That's the whole adoption surface: form field, table column, table filter. Ship that on one resource, eyeball the flag rendering, then roll it out.

Implementation Patterns

Use all three together, on the same attribute name. The value of this package is that the field, the column, and the filter all agree on the stored representation. Wiring only the form field and then displaying the raw code in a TextColumn throws away the reason to install it. Treat country_code as a single, consistently-named attribute across every resource and the admin UI stays coherent.

Pair with a phone field, but don't expect phone logic. This package is a country code select — it does not validate, format, or parse phone numbers. The common pattern is a Select-style country code next to a TextInput::make('phone')->tel(), with your own validation in a FormRequest or ->rules().

Normalize casing at the model boundary. Given the "Update lower function" fix in the 1.x line, the column's flag lookup is case-sensitive against lowercase codes. Pick one convention (lowercase) and enforce it with a mutator, so seeders, imports, and API writes can't desync the UI:

protected function countryCode(): Attribute
{
    return Attribute::make(
        set: fn (?string $value) => $value ? strtolower($value) : null,
    );
}

Drive dependent fields with ->live(). A frequent workflow is "country code changes → re-render the phone/state field or adjust a prefix":

CountryCodeSelect::make('country_code')
    ->live()
    ->afterStateUpdated(fn (Set $set) => $set('phone_prefix', null)),

Because it's a Select, this costs nothing and works inside modals and repeaters.

Extract the trio into a reusable schema fragment. If more than two resources need it, put the three definitions behind static helpers (AddressSchema::countryCodeField(), etc.) so a future package swap or config change is one file, not fifteen.

It composes anywhere a form/table does — relation managers, Repeater items, action modal forms (->form([...])), and custom pages. There's no panel plugin to register, so there's no "supported contexts" caveat to worry about.

Filtering beyond the table: the filter is a standard Filament filter, so it also works in custom table widgets that build their own Table. For dashboard aggregates, just read the query string convention and apply where('country_code', $code) yourself — don't try to reuse the filter class outside a table.

Gotchas and Tips

Pin to ^2.1.1, not ^2.0. v2.1.1 is literally "Fix path for countrycode.css registration" — meaning the CSS/flag styling was broken in 2.1.0. If flags render as blank boxes or the column looks unstyled, check the installed version before you go debugging your theme.

PHP floor moved. v2.1.0 dropped PHP 8.2 and added 8.5 support. If you're on 8.2 and pinning ^2.0, Composer will resolve you to 2.0.x — which silently keeps you off the CSS fix. Verify with composer show tapp/filament-country-code-field.

Empty/null state used to throw — guard legacy pins. v1.0.1 fixed "exception when column state is empty". On any 1.x below that, a nullable country_code blows up the table. Even on current versions, add a ->placeholder('—') to the column so nulls look intentional rather than broken.

Filament 5 support landed in 2.0.2, Filament 4 in 2.0.0. If you're on Filament 5 and pinned 2.0.0/2.0.1, that's your bug.

Debugging "the flag doesn't show": in order — (1) dump the raw DB value and confirm casing, (2) confirm the code exists in the published config's country list, (3) run php artisan filament:assets and check the file actually exists in public/, (4) confirm your custom theme (if you have one) imports/registers the package CSS. Steps 1 and 2 are the culprits most of the time and cost nothing to check.

Custom themes are the sharp edge. Packages that register their own CSS are the ones that break under custom Filament themes. If you run a theme built with filament:theme, verify the flag styles survive a production build before rolling out — the CSS path bug above is exactly this failure mode.

Backfill before you switch a column over. If country_code currently stores "United States", "+1", or mixed-case codes, migrating to this column will render blanks. Write a one-off normalizing migration, then swap the component.

Localization is partial. pt_BR was added as a contribution; other locales come from wherever the options list is defined. If country names must be translated for your admin, plan to publish/override the language files or subclass the component and supply your own options — don't assume your locale is covered.

Keep a fallback in your back pocket. 21 stars and zero dependents means no ecosystem to lean on and no support guarantee. The whole component is a Select with an options array and a CSS class, so a drop-in replacement is ~15 lines if the package stalls on a future Filament major. Add one smoke test of your own (render the resource form + table) so a Filament upgrade that breaks it fails in CI, not in production.

Contribute upstream rather than forking. The repo's history is tiny, focused PRs from a handful of people (lowercase fix, CSS path, Filament 4/5 support, a translation). That's the kind of package where a one-line PR gets merged — preferable to a private fork you'll have to rebase forever.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk