adrolli/filament-title-with-slug
Installation:
composer require adrolli/filament-title-with-slug
Publish the config (optional):
php artisan vendor:publish --provider="Adrolli\FilamentTitleWithSlug\FilamentTitleWithSlugServiceProvider"
First Use Case:
Replace a standard TextInput or Textarea for a title field in a Filament form with TitleWithSlugInput:
use Adrolli\FilamentTitleWithSlug\TitleWithSlugInput;
TitleWithSlugInput::make(
fieldTitle: 'title',
fieldSlug: 'slug',
)
->rules(['title' => 'required|max:255', 'slug' => 'required|unique:posts,slug']),
Where to Look First:
config/filament-title-with-slug.php for default settings.Basic Integration: Replace a Filament form field for a title/slug pair:
TitleWithSlugInput::make('name', 'slug')
->columnSpanFull()
->required(),
Custom Slug Generation: Override the default slugifier (e.g., for SEO-friendly URLs):
TitleWithSlugInput::make('title', 'slug')
->slugifier(fn(string $title): string => Str::slug($title, '-').'-custom'),
Dynamic "Visit" Links: Use a custom route resolver for the "View" button:
TitleWithSlugInput::make('title', 'slug')
->visitRoute(fn($record) => route('posts.show', $record)),
Conditional Slug Editing: Disable slug editing for certain records (e.g., drafts):
TitleWithSlugInput::make('title', 'slug')
->editableSlug(fn($record) => $record->is_published),
Localization: Translate labels and placeholders:
TitleWithSlugInput::make('title', 'slug')
->label(__('filament-title-with-slug::fields.title.label'))
->placeholder(__('filament-title-with-slug::fields.title.placeholder')),
Validation Integration: Sync validation rules with model rules:
TitleWithSlugInput::make('title', 'slug')
->rules([
'title' => 'required|max:255|unique:posts,title,'.$record->id,
'slug' => 'required|unique:posts,slug,'.$record->id,
]),
Livewire Hooks: Listen to slug changes for real-time updates:
protected function getTitleWithSlugInputListeners(): array
{
return [
'slug-updated' => fn($slug) => $this->syncSlugToMeta($slug),
];
}
Model Observers: Trigger actions when slugs are updated:
class PostObserver
{
public function saved(Post $post)
{
if ($post->wasChanged('slug')) {
// Redirect SEO crawlers, log changes, etc.
}
}
}
Custom UI Extensions: Extend the component via Blade or JavaScript (e.g., add a "slug preview" tooltip):
<x-filament-title-with-slug::input
wire:model="state.title"
wire:model.defer="state.slug"
x-data="{
preview: @entangle('state.slug'),
showPreview: false,
}"
x-on:mouseenter="showPreview = true"
x-on:mouseleave="showPreview = false"
>
<div x-show="showPreview" x-text="`Preview: ${preview}`" class="absolute bg-gray-800 text-white p-2 rounded"></div>
</x-filament-title-with-slug::input>
Slug Uniqueness Conflicts:
->uniqueRule() or custom validation:
TitleWithSlugInput::make('title', 'slug')
->uniqueRule('posts', 'slug', ignoreRecord: true),
Livewire State Mismatch:
wire:model.defer is used and save() is called explicitly if needed.Route Caching:
visitRoute may fail if routes aren’t cached.route() helper with cached parameters.Dark Mode Styling:
dark:bg-gray-800).Slugifier Edge Cases:
->slugifier(fn($title) => preg_replace('/[^\pL0-9\-_]/u', '-', $title)),
config/filament-title-with-slug.php for unexpected behavior (e.g., disabled features).wire:ignore or JavaScript to log slug changes for debugging:
document.addEventListener('slug-updated', (e) => {
console.log('Slug updated:', e.detail);
});
cp vendor/adrolli/filament-title-with-slug/resources/views/input.blade.php resources/views/vendor/filament-title-with-slug/input.blade.php
Custom Slugifier: Replace the default slugifier with a service provider:
public function boot()
{
TitleWithSlugInput::configureUsing(function (TitleWithSlugInput $component) {
$component->slugifier(app(\App\Services\CustomSlugifier::class));
});
}
Add-on Fields: Extend the component to include additional fields (e.g., SEO meta tags):
TitleWithSlugInput::make('title', 'slug')
->extraFields([
TextInput::make('meta_description')
->columnSpan('full')
->maxLength(160),
]),
Event Listeners: Listen to slug changes globally:
TitleWithSlugInput::listen('slug-updated', function ($slug, $record) {
// Trigger analytics, update search index, etc.
});
Localization Fallback: Provide fallback translations for missing keys:
TitleWithSlugInput::make('title', 'slug')
->translateLabelsUsing(fn($key, $default) => __("filament-title-with-slug::{$key}", ['default' => $default])),
Performance:
TitleWithSlugInput::make('title', 'slug')
->autoGenerateSlug(false),
->columnSpan() wisely to avoid layout issues on small screens.How can I help you explore Laravel packages today?