camya / filament-title-with-slug

"Title With Slug" Input - Easy Permalink Slugs for Filament Forms (PHP / Laravel / Livewire)
MIT License
130 stars 39 forks source link

Use getAttributeValue to get the attribute value #20

Closed chosten closed 1 year ago

chosten commented 1 year ago

My use case is a translated title/slug field, both stored in a JSON column but I believe it applies anytime you try to use a property of a JSON field for the fieldSlug (eg: 'slug.en'). In that case an exception is raised when the SlugInput is readling the attribute value and Model::preventAccessingMissingAttributes is enabled. To fix this we can directly call the getAttributeValue method of the model instead of the magic methods.

camya commented 1 year ago

Hi @chosten, thank for the PR.

Do you use the Spatie Laravel Translatable package for your translations? If yes, maybe we can add a small how-to in the "Usage & examples" section of the documentation.

chosten commented 1 year ago

Yes I do. But I don't use it with the Translatable trait provided by Filament. Instead I use tabs for each locale.

Sorry I'm not confident writing the documentation myself but I can provide an example. Here is what I came up with:

$locales = ['en' => 'English', 'fr' => 'Français'];
$tabs = [];
foreach ($locales as $locale => $localeName) {
    $tabs[] = Tabs\Tab::make($localeName)
        ->schema([
            TitleWithSlugInput::make(
                fieldTitle: "title.$locale",
                fieldSlug: "slug.$locale",
                titleLabel: __('Title'),
                titlePlaceholder: __('Title'),
                urlPath: "/$locale/",
                slugRuleUniqueParameters: [
                    'column' => "slug->$locale",
                    'ignorable' => fn (?Model $record) => $record,
                ],
            ),
        ]);
}

I'm not sure this is even needed if you use the Translatable trait, but I haven't tried it. But I suspect there will be a problem with the uniqueness of the slug.

camya commented 1 year ago

Hm, I tried your example for the documentation. Unfortunately the "url preview" does not work if using the translation. (using parameter urlVisitLinkRoute)

Do you have a working preview url in your implementation?

The problem is in the getRecordSlug() method in SlugInput.php. The record recordSlug is slug.en, but after Filament's evaluation it's null. Than the getRecordUrl() returns early and no url is generated.

// $this->recordSlug is 'slug.en', becomes 'null'.
public function getRecordSlug(): ?string
{
    return $this->evaluate($this->recordSlug);
}
chosten commented 1 year ago

You are right there is still a problem even with getAttributeValue. What do you think about this way:

->slugInputRecordSlug(fn (?Model $record) => data_get($record?->attributesToArray(), $fieldSlug))

It's actually the way Filament use to get the data to fill the forms.

chosten commented 1 year ago

As a side note, I think you should use the getRecordSlug instead for this line: : $this->getBaseUrl().$this->getBasePath().$this->evaluate($this->recordSlug);

As in: : $this->getBaseUrl().$this->getBasePath().$this->getRecordSlug();

chosten commented 1 year ago

@camya Do you want another PR for this ?