Skip to content

Commit

Permalink
Improve field property handling (#20)
Browse files Browse the repository at this point in the history
* Make field properties dynamic

Instead of accessing and setting properties on a static config array, we are now calling the property methods on demand. This is helpful if you change a field in the `hydratedFields` callback. For instance, if you change the options of a select field, the default value will now automatically take those new options into account. Before this change, you had to manually change the default value to reflect the changes made to the options.

* Use fallback of `get` method

* Make inline label translatable

* Get handle from handle method

* Make properties changeable

* Move unchangeable methods into class

`id`, `handle`, and `key` are essential field properties that should never be changed. They are different from config properties like `options` and `default`.

* The `view` is also an unchangeable property

* Keys should always be snake case

* Make integer input type changeable

* Fix captcha response being saved to file

* Fresh composer.lock

* Make the view a changeable property again

* Fix styling

* Update README.md

* Make things look prettier with shorter syntax

* Make lines more readable

* Fall back to config item if property doesn’t exist

* Update README.md

* Update README.md

* Preserve the captcha response on form reset

* Fix styling

* Make sure we can get multi-word keys with methods

* Make view a property instead of constant

* Users should use the magic methods and properties

* Use get_class_methods instead of ReflectionClass

* Make it look prettier with arrow function

* Improve readability

* Limit access to methods that contain `Property`

* Move properties back to traits

Co-authored-by: aerni <aerni@users.noreply.github.com>
  • Loading branch information
aerni and aerni authored Jul 17, 2022
1 parent 1ea4efe commit d2861e3
Show file tree
Hide file tree
Showing 38 changed files with 302 additions and 329 deletions.
39 changes: 17 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ Sometimes you need more control over the markup of your form. If you decide to g

```blade
@formField('name', [
'view' => 'fields.nameInput'
'view' => 'nameInput',
'tooltip' => 'Please enter your full name'
])
```
Expand All @@ -245,7 +245,9 @@ Use the properties in the field's view like this:
{{ $field->tooltip }}
```

>**Note:** The `view` property is a special one, as it will take the folder of the current theme into account.
>**Note:** The `view` property will look for the view in the theme's fields directory: `{theme}/fields/{view}.blade.php`.
>**Note:** There are a few properties such as options, default and conditions that won't work correctly when assigned in the view. This is due to the hydration lifecycle of Livewire. If you want to change those properties, you should create a custom component instead.
## Themes

Expand Down Expand Up @@ -285,7 +287,7 @@ Livewire Forms is smart enough to autoload custom components by matching the cla
### Field Models

Field models are responsible to generate a field's properties like `id`, `handle`, and `label`. For instance, all the fields of type `\Statamic\Fieldtypes\Select::class` are bound to the `\Aerni\LivewireForms\Fields\Select::class` model. A field property is created for each model method ending with `Property`, e.g. `optionsProperty()` will generate an `options` property.
Field models are responsible for generating a field's properties like `view`, `label`, and `rules`. For instance, all the fields of type `\Statamic\Fieldtypes\Select::class` are bound to the `\Aerni\LivewireForms\Fields\Select::class` model. A field property is created for each model method ending with `Property`, e.g. `optionsProperty()` will generate an `options` property.

To change a fields default model, simply change the binding in the `models` property in your component:

Expand Down Expand Up @@ -348,27 +350,23 @@ In the following example we want to dynamically generate the options of a select

#### Using a custom field model

We start by creating a new `SelectProduct` field model class that extends the default `Select` model class. We then override the `optionsProperty` method to return our options from a collection. We also override the `viewProperty` method to assign the unique view for this field. We are making use of the `Component::getView()` method, which takes the current theme into consideration.
We start by creating a new `SelectProduct` field model class that extends the default `Select` model class. We then override the `optionsProperty` method to return our options from a collection. We also assign a different view using the `$view` class property.

```php
namespace App\Fields;

use Aerni\LivewireForms\Facades\Component;
use Aerni\LivewireForms\Fields\Select as Base;
use Aerni\LivewireForms\Fields\Select;
use Statamic\Facades\Entry;

class SelectProduct extends Base
class SelectProduct extends Select
{
public function optionsProperty(): array
{
return Entry::whereCollection('products')->mapWithKeys(function ($product) {
return [$product->slug() => $product->get('title')];
})->all();
}
protected static string $view = 'select_product';

public function viewProperty(): string
public function optionsProperty(): array
{
return Component::getView('fields.select_product');
return Entry::whereCollection('products')
->mapWithKeys(fn ($product) => [$product->slug() => $product->get('title')])
->all();
}
}
```
Expand All @@ -395,22 +393,19 @@ Instead of defining a new field model, we can also achieve the same thing using
```php
namespace App\Http\Livewire;

use Aerni\LivewireForms\Facades\Component;
use Aerni\LivewireForms\Http\Livewire\BaseForm;

class ContactForm extends BaseForm
{
protected function hydratedFields(Fields $fields): void
{
$options = Entry::whereCollection('products')->mapWithKeys(function ($product) {
return [$product->slug() => $product->get('title')];
})->all();

$view = Component::getView('fields.select_product');
$options = Entry::whereCollection('products')
->mapWithKeys(fn ($product) => [$product->slug() => $product->get('title')])
->all();

$fields->get('products')
->options($options)
->view($view);
->view('select_product');
}
}
```
Expand Down
Loading

0 comments on commit d2861e3

Please sign in to comment.