PHPackages                             syzygymedia/filament-pro6pp-autocomplete - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. syzygymedia/filament-pro6pp-autocomplete

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

syzygymedia/filament-pro6pp-autocomplete
========================================

A FilamentPHP plugin that validates Duthc, Belgium and German postal codes and automatically fills address fields (street, neighborhood, city, state, country) using Pro6pp as the primary source.

04PHP

Since Jan 26Pushed 3mo agoCompare

[ Source](https://github.com/syzygymedia/filament-pro6pp-autocomplete)[ Packagist](https://packagist.org/packages/syzygymedia/filament-pro6pp-autocomplete)[ RSS](/packages/syzygymedia-filament-pro6pp-autocomplete/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Filament Pro6pp Autocomplete
============================

[](#filament-pro6pp-autocomplete)

A clean and simple Filament v4 plugin that integrates Pro6PP postal code autocomplete functionality. This plugin provides seamless address lookup with support for multiple European countries.

[![hero.png](https://raw.githubusercontent.com/syzygymedia/filament-pro6pp-autocomplete/main/art/hero.png)](https://raw.githubusercontent.com/syzygymedia/filament-pro6pp-autocomplete/main/art/hero.png)

Features
--------

[](#features)

- 🌍 **Multi-country support**: Netherlands, Belgium, Luxembourg, Germany, France, Denmark, Austria, Switzerland
- ⚡ **Backend API calls**: All API requests are securely handled server-side
- 🎨 **Country-specific validation**: Automatic field requirements and formatting based on country
- 🎯 **Smart field mapping**: Automatically populates form fields with API response
- 🔘 **Built-in search button**: Clean suffix action button with magnifying glass icon
- ✅ **Native Filament patterns**: Uses TextInput + suffixAction - no custom views needed
- 🚫 **Zero configuration**: No traits, macros, or JavaScript required

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Filament v4.x
- Laravel 10.x, 11.x or 12.x
- Livewire 3.x
- Pro6PP API key (get yours at [pro6pp.nl](https://www.pro6pp.nl))

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require syzygy/filament-pro6pp-autocomplete
```

Publish the configuration file:

```
php artisan vendor:publish --tag="filament-pro6pp-config"
```

Add your Pro6PP API key to your `.env` file:

```
PRO6PP_API_KEY=your-api-key-here
```

Usage
-----

[](#usage)

### Basic Example (Netherlands)

[](#basic-example-netherlands)

For the Netherlands, postal code AND street number are required:

```
use Syzygy\FilamentPro6pp\Forms\Components\Pro6ppAutocomplete;
use Syzygy\FilamentPro6pp\Enums\Pro6ppLanguage;
use Filament\Forms\Components\TextInput;

public function form(Form $form): Form
{
    return $form->schema([
        Pro6ppAutocomplete::make('postal_code')
            ->language(Pro6ppLanguage::NL),

        TextInput::make('street_number')
            ->label('House Number')
            ->required(),  // Required for NL lookups

        // These fields will be auto-filled when the search button is clicked
        TextInput::make('street')->label('Street'),
        TextInput::make('settlement')->label('City'),
        TextInput::make('municipality')->label('Municipality'),
        TextInput::make('province')->label('Province'),
    ]);
}
```

### Complete Example with Custom Field Bindings (Netherlands)

[](#complete-example-with-custom-field-bindings-netherlands)

```
use Syzygy\FilamentPro6pp\Forms\Components\Pro6ppAutocomplete;
use Syzygy\FilamentPro6pp\Enums\Pro6ppLanguage;
use Filament\Forms\Components\TextInput;

public function form(Form $form): Form
{
    return $form->schema([
        Pro6ppAutocomplete::make('address_lookup')
            ->language(Pro6ppLanguage::NL)
            ->bindStreet('street')
            ->bindStreetNumber('street_number')
            ->bindSettlement('settlement')
            ->bindProvince('province')
            ->bindPostalCode('postal_code')
            ->bindCountry('country')
            ->bindCountryCode('country_code')
            ->bindLat('latitude')
            ->bindLng('longitude')
            ->nextFocusField('street_number'),

        TextInput::make('street_number')
            ->label('House Number')
            ->required(),  // Required for NL lookups

        // These fields will be auto-filled after lookup
        TextInput::make('street')->label('Street'),
        TextInput::make('settlement')->label('City'),
        TextInput::make('municipality')->label('Municipality'),
        TextInput::make('province')->label('Province'),
        TextInput::make('country')->label('Country'),
        TextInput::make('country_code')->label('Country Code'),
        TextInput::make('latitude')->label('Latitude'),
        TextInput::make('longitude')->label('Longitude'),
    ]);
}
```

### Belgium / Luxembourg Example

[](#belgium--luxembourg-example)

For Belgium and Luxembourg, the user must also enter a street name before searching:

```
use Syzygy\FilamentPro6pp\Forms\Components\Pro6ppAutocomplete;
use Syzygy\FilamentPro6pp\Enums\Pro6ppLanguage;
use Filament\Forms\Components\TextInput;

public function form(Form $form): Form
{
    return $form->schema([
        Pro6ppAutocomplete::make('postal_code')
            ->language(Pro6ppLanguage::BE) // or Pro6ppLanguage::LU
            ->streetField('street'), // Tell component where to find street input

        TextInput::make('street')->label('Street')->required(),

        // These fields will be auto-filled
        TextInput::make('street_number')->label('House Number'),
        TextInput::make('settlement')->label('City'),
        TextInput::make('municipality')->label('Municipality'),
    ]);
}
```

### Germany / France / Denmark / Austria / Switzerland Example

[](#germany--france--denmark--austria--switzerland-example)

For these countries, users must enter postal code, city, and street:

```
use Syzygy\FilamentPro6pp\Forms\Components\Pro6ppAutocomplete;
use Syzygy\FilamentPro6pp\Enums\Pro6ppLanguage;
use Filament\Forms\Components\TextInput;

public function form(Form $form): Form
{
    return $form->schema([
        Pro6ppAutocomplete::make('postal_code')
            ->language(Pro6ppLanguage::DE) // or FR, DK, AT, CH
            ->settlementField('settlement')  // Where to find city
            ->streetField('street'),         // Where to find street

        TextInput::make('settlement')->label('City')->required(),
        TextInput::make('street')->label('Street')->required(),

        // These fields will be auto-filled
        TextInput::make('street_number')->label('House Number'),
        TextInput::make('municipality')->label('Municipality'),
        TextInput::make('state')->label('State'),
    ]);
}
```

Component Methods
-----------------

[](#component-methods)

### Configuration Methods

[](#configuration-methods)

#### `language(Pro6ppLanguage|string $language)`

[](#languagepro6pplanguagestring-language)

Set the country/language for the autocomplete service.

```
Pro6ppAutocomplete::make('postal_code')
    ->language(Pro6ppLanguage::NL)
```

#### `settlementField(?string $field)`

[](#settlementfieldstring-field)

For countries requiring city input (DE, FR, DK, AT, CH), specify which form field contains the city/settlement.

```
Pro6ppAutocomplete::make('postal_code')
    ->language(Pro6ppLanguage::DE)
    ->settlementField('city')  // Read from 'city' field
```

#### `streetField(?string $field)`

[](#streetfieldstring-field)

For countries requiring street input (BE, LU, DE, FR, DK, AT, CH), specify which form field contains the street.

```
Pro6ppAutocomplete::make('postal_code')
    ->language(Pro6ppLanguage::BE)
    ->streetField('street_name')  // Read from 'street_name' field
```

#### `nextFocusField(?string $field)`

[](#nextfocusfieldstring-field)

Set which field should receive focus after successful lookup (default: `'street_number'`).

```
Pro6ppAutocomplete::make('postal_code')
    ->nextFocusField('house_number')
```

### Field Binding Methods

[](#field-binding-methods)

By default, the component maps API responses to standard field names. Customize mappings with these methods:

#### Standard Fields (All Countries)

[](#standard-fields-all-countries)

- `bindPostalCode(string $field)` - Default: `'postal_code'`
- `bindStreet(string $field)` - Default: `'street'`
- `bindStreetNumber(string $field)` - Default: `'street_number'`
- `bindPremise(string $field)` - Default: `'premise'`
- `bindSettlement(string $field)` - Default: `'settlement'`
- `bindCountry(string $field)` - Default: `'country'`
- `bindCountryCode(string $field)` - Default: `'country_code'`
- `bindLat(string $field)` - Default: `'lat'`
- `bindLng(string $field)` - Default: `'lng'`

#### Country-Specific Fields

[](#country-specific-fields)

- `bindNeighbourhood(string $field)` - NL: Neighborhood
- `bindDistrict(string $field)` - NL, LU, DE, AT, CH: District
- `bindMunicipality(string $field)` - NL, BE, LU, DE, DK, AT, CH: Municipality
- `bindProvince(string $field)` - NL, BE, DK: Province
- `bindRegion(string $field)` - BE, FR, DK: Region
- `bindBox(string $field)` - BE: Box number
- `bindBoxPrefix(string $field)` - BE: Box prefix
- `bindCanton(string $field)` - LU, CH: Canton
- `bindDepartment(string $field)` - FR: Department
- `bindCommune(string $field)` - FR: Commune
- `bindState(string $field)` - DE, AT: State/Bundesland

### Example with Custom Field Names

[](#example-with-custom-field-names)

```
Pro6ppAutocomplete::make('zip_code')
    ->language(Pro6ppLanguage::NL)
    ->bindPostalCode('zip_code')      // Map to 'zip_code' instead of 'postal_code'
    ->bindStreet('address_line_1')    // Map to 'address_line_1'
    ->bindSettlement('city_name')     // Map to 'city_name'
    ->bindProvince('province_name')   // Map to 'province_name'
    ->nextFocusField('house_nr')      // Focus 'house_nr' field after lookup
```

How It Works
------------

[](#how-it-works)

### Architecture

[](#architecture)

1. **User Input**: User enters required information (postal code, and optionally city/street)
2. **Click Search Button**: User clicks the magnifying glass suffix action button
3. **Validation**: Filament validates the postal code field
4. **Backend Call**: Component reads form values and calls Pro6ppService
5. **API Request**: Pro6ppService makes secure backend request to Pro6PP API
6. **Field Population**: Response data populates form fields using Filament's `Set` helper
7. **Focus Management**: Optional auto-focus to next field

### Technical Implementation

[](#technical-implementation)

The component extends Filament's `TextInput` and uses `suffixAction()` to add a search button. The action closure receives the `Set $set` helper, which is used to update other form fields - this is the standard Filament pattern (inspired by [filament-smart-cep](https://github.com/otavio-araujo/filament-smart-cep)).

```
protected function setUp(): void
{
    parent::setUp();

    $this->suffixAction(
        fn (): Action => Action::make('pro6ppLookup')
            ->icon('heroicon-o-magnifying-glass')
            ->action(function (Livewire $livewire, Set $set) {
                // Validate, call API, update fields with $set()
            })
    );
}
```

Country Requirements
--------------------

[](#country-requirements)

Different countries have different lookup requirements:

CountryCodePostal FormatRequired FieldsAdditional Data🇳🇱 NetherlandsNL1234AB (4 digits + 2 letters)Postal code + Street numberNeighborhood, District🇧🇪 BelgiumBE1234 (4 digits)Postal code + StreetBox number, Region🇱🇺 LuxembourgLU1234 (4 digits)Postal code + StreetCanton, District🇩🇪 GermanyDE12345 (5 digits)Postal code + City + StreetState (Bundesland)🇫🇷 FranceFR12345 (5 digits)Postal code + City + StreetDepartment, Region🇩🇰 DenmarkDK1234 (4 digits)Postal code + City + StreetRegion🇦🇹 AustriaAT1234 (4 digits)Postal code + City + StreetState (Bundesland)🇨🇭 SwitzerlandCH1234 (4 digits)Postal code + City + StreetCantonValidation
----------

[](#validation)

### Input Masking

[](#input-masking)

The component automatically applies input masks based on the selected country:

- **NL**: `9999aa` (e.g., 1012AB)
- **DE, FR**: `99999` (e.g., 10115)
- **BE, LU, DK, AT, CH**: `9999` (e.g., 1000)

### Server-Side Validation

[](#server-side-validation)

Pro6ppService handles all backend validation:

- API key verification
- Required field checking
- Postal code sanitization
- Error handling with user notifications

Error Handling
--------------

[](#error-handling)

The plugin provides comprehensive error handling with user-friendly notifications:

- **Missing API Key**: Notification prompts user to add PRO6PP\_API\_KEY to .env
- **Missing Required Fields**: Warning about incomplete data before API call
- **Address Not Found**: Notification when Pro6PP API returns no results
- **Connection Error**: Handles API timeout and connection issues gracefully
- **API Errors**: Displays specific error messages from Pro6PP

Testing
-------

[](#testing)

### Example Test Data

[](#example-test-data)

**Netherlands (NL):**

```
Postal code: 1012AB → Amsterdam addresses
```

**Belgium (BE):**

```
Postal code: 1000
Street: Wetstraat → Brussels addresses
```

**Germany (DE):**

```
Postal code: 10115
City: Berlin
Street: Unter den Linden
```

**France (FR):**

```
Postal code: 75001
City: Paris
Street: Rue de Rivoli

```

Technical Details
-----------------

[](#technical-details)

### Stack

[](#stack)

- **Backend**: Laravel + Filament v4
- **Component**: Extends `Filament\Forms\Components\TextInput`
- **Action Pattern**: Uses `suffixAction()` with `Set $set` helper
- **API**: Pro6PP v2 REST API with HTTP Client

### No Custom Views Required

[](#no-custom-views-required)

Unlike many Filament plugins, this package doesn't require custom Blade views. It uses Filament's native `TextInput` with a `suffixAction`, making it simple, maintainable, and future-proof.

### Data Flow

[](#data-flow)

```
User fills fields → Clicks suffix button → Filament validates
→ Action closure executes → Reads form values via data_get()
→ Calls Pro6ppService → HTTP request to Pro6PP API
→ Response formatted → $set() updates form fields → Optional auto-focus
```

Credits
-------

[](#credits)

- Inspired by [filament-smart-cep](https://github.com/otavio-araujo/filament-smart-cep) by Otavio Araujo
- Built by [Syzygy Media](https://github.com/syzygymedia)

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for recent changes.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

19

—

LowBetter than 10% of packages

Maintenance54

Moderate activity, may be stable

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity12

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/fd0c74f8faf4554941c0bec0a124c068d860030bafcb64ee4823ebe4a54d6640?d=identicon)[syzygymedia](/maintainers/syzygymedia)

---

Top Contributors

[![eelco2k](https://avatars.githubusercontent.com/u/878103?v=4)](https://github.com/eelco2k "eelco2k (6 commits)")

### Embed Badge

![Health badge](/badges/syzygymedia-filament-pro6pp-autocomplete/health.svg)

```
[![Health](https://phpackages.com/badges/syzygymedia-filament-pro6pp-autocomplete/health.svg)](https://phpackages.com/packages/syzygymedia-filament-pro6pp-autocomplete)
```

###  Alternatives

[webmozart/assert

Assertions to validate method input/output with nice error messages.

7.6k894.0M1.2k](/packages/webmozart-assert)[bensampo/laravel-enum

Simple, extensible and powerful enumeration implementation for Laravel.

2.0k15.9M104](/packages/bensampo-laravel-enum)[swaggest/json-schema

High definition PHP structures with JSON-schema based validation

48612.5M73](/packages/swaggest-json-schema)[stevebauman/purify

An HTML Purifier / Sanitizer for Laravel

5325.6M19](/packages/stevebauman-purify)[ashallendesign/laravel-config-validator

A package for validating your Laravel app's config.

217905.3k5](/packages/ashallendesign-laravel-config-validator)[crazybooot/base64-validation

Laravel validators for base64 encoded files

1341.9M8](/packages/crazybooot-base64-validation)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
