From 708bab5b2c55463f2a13ea39924fe22d1d1fd712 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 14 Oct 2022 17:24:03 +0200 Subject: [PATCH 001/121] v0.6 (#22) --- table-bulk-actions.md | 72 ++++++++++++++ table-exports.md | 82 ++++++++++++++++ table-overview.md | 89 ++++++++++++++++-- table-query-builder.md | 170 ++++++++++++++++++++-------------- table-spatie-query-builder.md | 106 +++++++++++++++++++++ 5 files changed, 440 insertions(+), 79 deletions(-) create mode 100644 table-bulk-actions.md create mode 100644 table-exports.md create mode 100644 table-spatie-query-builder.md diff --git a/table-bulk-actions.md b/table-bulk-actions.md new file mode 100644 index 0000000..6a5cd2b --- /dev/null +++ b/table-bulk-actions.md @@ -0,0 +1,72 @@ +# Table Bulk Actions + +The Table component supports performing Bulk Actions. First, you must register a supporting route using the `spladeTable()` method on the `Route` facade. As of version 0.6, the automatic installer does this for you. If you need to register the route manually, make sure it uses the `web` and `splade` Middleware, for example, in `web.php`: + +```php +Route::middleware('splade')->group(function () { + Route::spladeTable(); +}); +``` + +## Configure a Bulk Action + +You may configure a Bulk Action on the `SpladeTable` instance: + +```php +public function configure(SpladeTable $table) +{ + $table->bulkAction('Touch timestamp', function (Project $project) { + $project->touch(); + }); +} +``` + +The `bulkAction` method has additional `before` and `after` arguments. You may use this to show a [Toast](/toasts.md) when the action has finished, or for example, to perform some logging: + +```php +$table->bulkAction( + label: 'Touch timestamp', + each: fn (Project $project) => $project->touch(), + before: fn () => info('Touching the selected projects'), + after: fn () => Toast::info('Timestamps updated!') +); +``` + +## Confirmation + +You may use the `confirm` argument to show a confirmation dialog before Splade perform the action: + +```php +$table->bulkAction( + label: 'Touch timestamp', + each: fn (Project $project) => $project->touch(), + confirm: true +); +``` + +In addition, you may customize the confirmation dialog: + +```php +$table->bulkAction( + label: 'Touch timestamp', + each: fn (Project $project) => $project->touch(), + confirm: 'Touch projects', + confirmText: 'Are you sure you want to touch the projects?', + confirmButton: 'Yes, touch all selected rows!', + cancelButton: 'No, do not touch!', +); +``` + +## Authorization + +Just like [Form Requests](https://laravel.com/docs/9.x/validation#authorizing-form-requests), you may use the `authorize` method to determine if the user has the authority to perform a Bulk Action: + +```php +class Projects extends AbstractTable +{ + public function authorize(Request $request) + { + return $request->user()->is_admin; + } +} +``` \ No newline at end of file diff --git a/table-exports.md b/table-exports.md new file mode 100644 index 0000000..ce65a52 --- /dev/null +++ b/table-exports.md @@ -0,0 +1,82 @@ +# Table Exports + +The Table component supports Exports. First, you must register a supporting route using the `spladeTable()` method on the `Route` facade. As of version 0.6, the automatic installer does this for you. If you need to register the route manually, make sure it uses the `web` and `splade` Middleware, for example, in `web.php`: + +```php +Route::middleware('splade')->group(function () { + Route::spladeTable(); +}); +``` + +Lastly, you need to install the [`maatwebsite/excel`](https://github.com/SpartnerNL/Laravel-Excel) package. Read the installation documentation carefully. If you want to export to PDF, you must install [additional libraries](https://docs.laravel-excel.com/3.1/exports/export-formats.html). + +## Configure an Export + +You may enable exporting with the `export()` method on the `SpladeTable` instance. It will configure an Excel Export by default. + +```php +public function configure(SpladeTable $table) +{ + $table->export(); +} +``` + +Of course, you may customize the export or add multiple exports. + +```php +use Maatwebsite\Excel\Excel; + +public function configure(SpladeTable $table) +{ + $table->export( + label: 'CSV export', + filename: 'projects.csv', + type: Excel::CSV + ); +} +``` + +## Customizing the export + +The `column` method has additional arguments you may use to customize the export. With the `exportAs` argument, you may transform the value or exclude the column from the export: + +```php +$table + ->column('name') + ->column('email', exportAs: false) + ->column('reference', exportAs: fn ($reference) => "#REF-{$reference}"); +``` + +The `exportFormat` allows you to [format](https://docs.laravel-excel.com/3.1/exports/column-formatting.html) the column, for example, to indicate that the column represents a currency: + +```php +use PhpOffice\PhpSpreadsheet\Style\NumberFormat; + +$table->column('amount', NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE); +``` + +Lastly, with the `exportStyling` method, you may style the column with an array or a callable: + +```php +use PhpOffice\PhpSpreadsheet\Style\Style; + +$table + ->column('name', exportStyling: ['font' => ['bold' => true]]) + ->column('email', exportStyling: function (Style $style) { + $style->getFont()->setBold(true); + }); +``` + +## Authorization + +Just like [Form Requests](https://laravel.com/docs/9.x/validation#authorizing-form-requests), you may use the `authorize` method to determine if the user has the authority to perform a Bulk Action: + +```php +class Projects extends AbstractTable +{ + public function authorize(Request $request) + { + return $request->user()->is_admin; + } +} +``` \ No newline at end of file diff --git a/table-overview.md b/table-overview.md index 07f6570..26a1eed 100644 --- a/table-overview.md +++ b/table-overview.md @@ -1,6 +1,6 @@ # Table (DataTables) Component -Splade has an advanced Table component that supports auto-fill, searching, filtering, sorting, toggling columns, and pagination. It's fully integrated and doesn't require any additional dependencies. Though optional, it integrates beautifully with Spatie's [Laravel Query Builder](https://github.com/spatie/laravel-query-builder). +Splade has an advanced Table component that supports auto-fill, searching, filtering, sorting, toggling columns, and pagination. You may also peform bulk actions and exports. Though optional, it integrates beautifully with Spatie's [Laravel Query Builder](https://github.com/spatie/laravel-query-builder). @@ -9,14 +9,11 @@ Splade has an advanced Table component that supports auto-fill, searching, filte You may use the `SpladeTable` class to configure the table in your controller. ```php -$perPage = request()->query('perPage', 15); - -$users = User::paginate($perPage); - return view('users.index', [ - 'users' => SpladeTable::for($users) + 'users' => SpladeTable::for(User::class) ->column('name') - ->column('email'), + ->column('email') + ->paginate(15), ]); ``` @@ -28,12 +25,88 @@ In your Blade template, use the `x-splade-table` component to render the table. That's all! It will automatically render the head, body, and pagination. +## Table Class + +Instead of using an *inline* `SpladeTable` in the controller, you may also create a dedicated Table class. This allows you to keep the configuration out of the controller, and lets you reuse the Table class. If you want to use Bulk Actions and Exports, a Table class is required. + +There's an Artisan command to create a Table class: + +```bash +php artisan make:table Users +``` + +You'll find the new Table class in the `app/Tables` folder. You may this class in the controller, instead of the *inline* instance: + +```php +use App\Tables\Users; + +return view('users.index', [ + 'users' => SpladeTable::for(User::class) // [tl! remove] + ->column('name') // [tl! remove] + ->column('email') // [tl! remove] + ->paginate(15), // [tl! remove] + + 'users' => Users::class, // [tl! add] +]); +``` + +The class consists of three methods that you'll need to implement: `authorize`, `for` and `configure`. + +### Implementing the `for` method + +If you create a new Table class, the `for` method has a default implemention. It returns a new query builder of the corresponding Eloquent Model: + +```php +public function for() +{ + return User::query(); +} +``` + +You may add additional constraints and apply scopes to query: + +```php +public function for() +{ + return User::query()->where('is_admin', 0); +} +``` + +Note that this will apply to all results. If you want to choose in the frontend between *admins* and *non-admins*, this is not the right place to apply the constraint. + +### Implementing the `configure` method + +The `configure` method gives you an instance of `SpladeTable`. Just like the *inline* example, here you may configure the columns, filters, pagination, search inputs, and more: + +```php +public function configure(SpladeTable $table) +{ + $table + ->column('name') + ->column('email') + ->paginate(15); +} +``` + +### Implementing the `authorize` method + +The `authorize` method is only used for Bulk Actions and Exports. Just like [Form Requests](https://laravel.com/docs/9.x/validation#authorizing-form-requests), you may determine if the user has the authority to perform such actions: + +```php +public function authorize(Request $request) +{ + return $request->user()->is_admin; +} +``` + +Instead of always returning `true`, you may also remove the method if you don't want to use authorization. + ## Pagination When the dataset is paginated, it will, by default, show a select dropdown to customize the number of rows per page. You may define a custom set of options using the `perPageOptions` method on the `SpladeTable`: ```php -SpladeTable::for($users) +SpladeTable::for(User::class) ->perPageOptions([50, 100, 200]) ->... ``` diff --git a/table-query-builder.md b/table-query-builder.md index 8a70437..4f8cbb9 100644 --- a/table-query-builder.md +++ b/table-query-builder.md @@ -1,15 +1,15 @@ -# Table with Laravel Query Builder +# Table built-in Query Builder -Besides rendering the head, body and pagination of table, the component supports many other features that goes great hand in hand with Spatie's Laravel Query Builder package. +Besides rendering the head, body and pagination of table, the component supports many other features like filtering, searching and sorting. ## Search Fields -With the `searchInput` method, you can specify which attributes are searchable. Search queries are passed to the URL query as a filter. This integrates seamlessly with the [filtering feature](https://spatie.be/docs/laravel-query-builder/v5/features/filtering) of the Laravel Query Builder package. +With the `searchInput` method, you can specify which attributes are searchable. Search queries are passed to the URL query as a filter. Though it's enough to pass in the column key, you may specify a custom label. ```php -SpladeTable::for($users) +$table ->searchInput('name') ->searchInput( key: 'framework', @@ -19,29 +19,27 @@ SpladeTable::for($users) ## Select Filters -Select Filters are similar to search fields but use a `select` element instead of an `input` element. This way, you can present the user a predefined set of options. Under the hood, this uses the same filtering feature of the Laravel Query Builder package. +Select Filters are similar to search fields but use a `select` element instead of an `input` element. This way, you can present the user a predefined set of options. The `selectFilter` method requires two arguments: the key, and a key-value array with the options. ```php -SpladeTable::for($users) - ->selectFilter('language_code', [ - 'en' => 'English', - 'nl' => 'Dutch', - ]); +$table->selectFilter('language_code', [ + 'en' => 'English', + 'nl' => 'Dutch', +]); ``` The `selectFilter` will, by default, add a *no filter* option to the array. You may disable this or specify a custom label for it. ```php -SpladeTable::for($users) - ->selectFilter( - key: 'language_code', - options: $languages, - label: 'Language', - noFilterOption: true - noFilterOptionLabel: 'All languages' - ); +$table->selectFilter( + key: 'language_code', + options: $languages, + label: 'Language', + noFilterOption: true + noFilterOptionLabel: 'All languages' +); ``` @@ -50,9 +48,8 @@ SpladeTable::for($users) With the `column` method, you can specify which columns you want to be toggleable, sortable, and searchable. You must pass in at least a key or label for each column. ```php -SpladeTable::for($users) +$table ->column('email', 'User Email') - ->column( key: 'name', label: 'User Name', @@ -71,86 +68,116 @@ SpladeTable::defaultColumnCanBeHidden(false); The `searchable` boolean is a shortcut to the `searchInput` method. The example below will essentially call `$table->searchInput('name', 'User Name')`. -## Global Search +### Default sort -You may enable Global Search with the `withGlobalSearch` method, and optionally specify a placeholder. +You may configure the default sorting with the `defaultSort()` method: ```php -SpladeTable::for($users) - ->withGlobalSearch(); +$table->defaultSort('name'); +``` -SpladeTable::for($users) - ->withGlobalSearch('Search through the data...'); +### Sort by Relationship column + +The Table supports sorting the results by a [Relationship](https://laravel.com/docs/9.x/eloquent-relationships) column. This requires the installation of the [`kirschbaum-development/eloquent-power-joins`](https://github.com/kirschbaum-development/eloquent-power-joins) package. + +```php +$table->column( + key: 'user.organization.name', + label: 'Organization', + sortable: true +); ``` -If you want to enable Global Search for every table by default, you may use the static `defaultGlobalSearch` method, for example, in the `AppServiceProvider` class: +## Global Search + +You may enable Global Search with the `withGlobalSearch` method, and optionally specify a placeholder. + +```php +$table->withGlobalSearch(columns: ['name', 'email']); +``` ```php -SpladeTable::defaultGlobalSearch(); -SpladeTable::defaultGlobalSearch('Default custom placeholder'); -SpladeTable::defaultGlobalSearch(false); // disable +$table->withGlobalSearch('Search through the data...', ['name', 'email']); ``` -## Example controller +## Example Table ```php where(function ($query) use ($value) { - Collection::wrap($value)->each(function ($value) use ($query) { - $query - ->orWhere('name', 'LIKE', "%{$value}%") - ->orWhere('email', 'LIKE', "%{$value}%"); - }); - }); - }); - - $users = QueryBuilder::for(User::class) + $table + ->withGlobalSearch(columns: ['name', 'email']) ->defaultSort('name') - ->allowedSorts(['name', 'email', 'language_code']) - ->allowedFilters(['name', 'email', 'language_code', $globalSearch]) - ->paginate(request()->query('perPage', 15)) - ->withQueryString(); - - return view('users.index', [ - 'users' => SpladeTable::for($users), - ->withGlobalSearch() - ->defaultSort('name') - ->column(key: 'name', searchable: true, sortable: true, canBeHidden: false) - ->column(key: 'email', searchable: true, sortable: true) - ->column(key: 'language_code', label: 'Language') - ->column(label: 'Actions') - ->selectFilter(key: 'language_code', label: 'Language', options: [ - 'en' => 'English', - 'nl' => 'Dutch', - ]); - ]); + ->column(key: 'name', searchable: true, sortable: true, canBeHidden: false) + ->column(key: 'email', searchable: true, sortable: true) + ->column(key: 'language_code', label: 'Language') + ->column(label: 'Actions') + ->selectFilter(key: 'language_code', label: 'Language', options: [ + 'en' => 'English', + 'nl' => 'Dutch', + ]) + ->paginate(15); } } ``` ### Custom column cells -When using auto-fill, you may want to transform the presented data for a specific column while leaving the other columns untouched. For this, you may use a cell template. This example is taken from the Example Controller above. +When using auto-fill, you may want to transform the presented data for a specific column while leaving the other columns untouched. For this, you may use a `cell` component. This example is taken from the Example Table above. ```blade - @cell('actions', $user) + + Edit + + +``` + +If you want to change the `$item` variable, you may use use the `as` attribute on the component: + +```blade + + Edit + +``` + +This component is a *scoped* component, so variables from outside the slot won't be available by default. If you still want to use a variable, you may use the `use` attribute: + +```blade +@php $message = 'Hello, world!'; @endphp + + +

{{ $message }}

+ Edit +
+``` + +When your templates uses multiple custom cells, you may set these variables as defaults on the parent table: + +```blade + + +

{{ $user->name }}

+
+ + Edit - @endcell +
``` @@ -159,10 +186,11 @@ When using auto-fill, you may want to transform the presented data for a specifi You may use the `rowLink` method to make one entire row clickable. ```php -SpladeTable::for($users) - ->rowLink(fn (User $user) => route('users.edit', ['id' => $user->id])) +$table->rowLink(fn (User $user) => route('users.edit', ['id' => $user->id])) ``` +If you want to open the URL in a [Modal or Slideover](/x-modal.md), you may use the `rowModal` or `rowSlideover` method. + ## Debounce The filter and selects elements have a default debounce time of 350ms. You may customize this: diff --git a/table-spatie-query-builder.md b/table-spatie-query-builder.md new file mode 100644 index 0000000..ae95ff7 --- /dev/null +++ b/table-spatie-query-builder.md @@ -0,0 +1,106 @@ +# Table with Spatie's Query Builder + +The Table component works seamlessly with Spatie's Laravel Query Builder package. You may use both an *inline* SpladeTable instance, as well as a dedicated Table class. Note that a Table class is required in order to use Bulk Actions and Exports. + +## Example with Table Instance + +```php +where(function ($query) use ($value) { + Collection::wrap($value)->each(function ($value) use ($query) { + $query + ->orWhere('name', 'LIKE', "%{$value}%") + ->orWhere('email', 'LIKE', "%{$value}%"); + }); + }); + }); + + return QueryBuilder::for(User::class) + ->defaultSort('name') + ->allowedSorts(['name', 'email', 'language_code']) + ->allowedFilters(['name', 'email', 'language_code', $globalSearch]); + } + + public function configure(SpladeTable $table) + { + $table + ->withGlobalSearch() + ->defaultSort('name') + ->column(key: 'name', searchable: true, sortable: true, canBeHidden: false) + ->column(key: 'email', searchable: true, sortable: true) + ->column(key: 'language_code', label: 'Language') + ->column(label: 'Actions') + ->selectFilter(key: 'language_code', label: 'Language', options: [ + 'en' => 'English', + 'nl' => 'Dutch', + ]) + ->paginate(15); + } +} +``` + +## Example controller with Inline Table + +```php +where(function ($query) use ($value) { + Collection::wrap($value)->each(function ($value) use ($query) { + $query + ->orWhere('name', 'LIKE', "%{$value}%") + ->orWhere('email', 'LIKE', "%{$value}%"); + }); + }); + }); + + $users = QueryBuilder::for(User::class) + ->defaultSort('name') + ->allowedSorts(['name', 'email', 'language_code']) + ->allowedFilters(['name', 'email', 'language_code', $globalSearch]); + + return view('users.index', [ + 'users' => SpladeTable::for($users), + ->withGlobalSearch() + ->defaultSort('name') + ->column(key: 'name', searchable: true, sortable: true, canBeHidden: false) + ->column(key: 'email', searchable: true, sortable: true) + ->column(key: 'language_code', label: 'Language') + ->column(label: 'Actions') + ->selectFilter(key: 'language_code', label: 'Language', options: [ + 'en' => 'English', + 'nl' => 'Dutch', + ]) + ->paginate(15), + ]); + } +} +``` + From ba30cf8e9a36f3efa5cf0d12f2179b368190d3df Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 14 Oct 2022 17:45:16 +0200 Subject: [PATCH 002/121] Update table-overview.md --- table-overview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/table-overview.md b/table-overview.md index 917ef79..d7ffedb 100644 --- a/table-overview.md +++ b/table-overview.md @@ -2,6 +2,7 @@ Splade has an advanced Table component that supports auto-fill, searching, filtering, sorting, toggling columns, and pagination. You may also perform bulk actions and exports. Though optional, it integrates beautifully with Spatie's [Laravel Query Builder](https://github.com/spatie/laravel-query-builder). +*This video is from a previous Splade version that did not have the built-in Query Builder yet. A recent intruction video will soon replace it!* ## Basic example From d3b1696a130305d3c55d2957a576db6dc4c31493 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 14 Oct 2022 17:45:46 +0200 Subject: [PATCH 003/121] Update table-overview.md --- table-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/table-overview.md b/table-overview.md index d7ffedb..f4c8abe 100644 --- a/table-overview.md +++ b/table-overview.md @@ -2,7 +2,7 @@ Splade has an advanced Table component that supports auto-fill, searching, filtering, sorting, toggling columns, and pagination. You may also perform bulk actions and exports. Though optional, it integrates beautifully with Spatie's [Laravel Query Builder](https://github.com/spatie/laravel-query-builder). -*This video is from a previous Splade version that did not have the built-in Query Builder yet. A recent intruction video will soon replace it!* +*This video is from a previous Splade version that did not have the built-in Query Builder yet. An updated instruction video will soon replace it!* ## Basic example From 168fe297189c125aa18c35b2aded940c7586bbff Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Fri, 14 Oct 2022 20:34:12 +0200 Subject: [PATCH 004/121] Update table-exports.md --- table-exports.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/table-exports.md b/table-exports.md index 5c0a978..bd79b26 100644 --- a/table-exports.md +++ b/table-exports.md @@ -52,7 +52,7 @@ The `exportFormat` allows you to [format](https://docs.laravel-excel.com/3.1/exp ```php use PhpOffice\PhpSpreadsheet\Style\NumberFormat; -$table->column('amount', NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE); +$table->column('amount', exportFormat: NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE); ``` Lastly, with the `exportStyling` method, you may style the column with an array or a callable: From 70ad329860cac9d46b747b243a9154cc741cd36e Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Mon, 17 Oct 2022 09:44:25 +0200 Subject: [PATCH 005/121] Update customization.md --- customization.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/customization.md b/customization.md index aa78577..6ab1000 100644 --- a/customization.md +++ b/customization.md @@ -3,7 +3,15 @@ You can find every bit of styling in Blade templates, so you never have to customize Vue components. You may publish the Blade templates using the `vendor:publish` Artisan command: ```bash -php artisan vendor:publish --provider="ProtoneMedia\Splade\ServiceProvider" +php artisan vendor:publish --provider="ProtoneMedia\Splade\ServiceProvider" --tag="views" ``` -Now the templates are available in the `/resources/views/vendor/splade` folder. \ No newline at end of file +Now the templates are available in the `/resources/views/vendor/splade` folder. + +## Laravel Configuration File + +You may also publish the configuration file. This allows you to configure settings like the Blade Component prefix, SEO defaults, SSR settings, and more. + +```bash +php artisan vendor:publish --provider="ProtoneMedia\Splade\ServiceProvider" --tag="config" +``` \ No newline at end of file From 2f9755abc5575f9acc115c63292a9a36f5bf01ca Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Mon, 17 Oct 2022 09:47:42 +0200 Subject: [PATCH 006/121] Additional links --- customization.md | 2 +- form-overview.md | 2 +- introducing-splade.md | 4 ++-- ssr.md | 2 +- title-meta.md | 2 +- x-flash.md | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/customization.md b/customization.md index 6ab1000..00cd8a8 100644 --- a/customization.md +++ b/customization.md @@ -8,7 +8,7 @@ php artisan vendor:publish --provider="ProtoneMedia\Splade\ServiceProvider" --ta Now the templates are available in the `/resources/views/vendor/splade` folder. -## Laravel Configuration File +## Laravel Configuration File (config/splade.php) You may also publish the configuration file. This allows you to configure settings like the Blade Component prefix, SEO defaults, SSR settings, and more. diff --git a/form-overview.md b/form-overview.md index 11bdd82..a94a806 100644 --- a/form-overview.md +++ b/form-overview.md @@ -29,7 +29,7 @@ All elements allow passing in a label, which will be rendered above the input el ``` -If you want to eliminate the `splade` prefix, you may update the `blade.component_prefix` key in the `splade.php` configuration file: +If you want to eliminate the `splade` prefix, you may update the `blade.component_prefix` key in the `splade.php` [configuration file](/customization.md): ```php return [ diff --git a/introducing-splade.md b/introducing-splade.md index 404f5a2..76723a8 100644 --- a/introducing-splade.md +++ b/introducing-splade.md @@ -13,11 +13,11 @@ To leverage the SPA capabilities of Splade, you may use the `` component i Contact ``` -If you're using an existing app, or maybe you don't like the `Link` component, you may configure Splade to transform all `` elements automatically. +If you're using an existing app, or maybe you don't like the `Link` component, you may configure Splade to transform all `` elements automatically as described in the [Link Component section](/x-link.md). ## The simplest component: a toggle -In the example below, we show an excerpt of the blog post. When the user clicks on the *Expand* button, it hides the excerpt and shows the full content. All Splade components are default prefixed with `splade`, but you may configure it without a prefix, resulting in a more readable `` component. +In the example below, we show an excerpt of the blog post. When the user clicks on the *Expand* button, it hides the excerpt and shows the full content. All Splade components are default prefixed with `splade`, but you may [configure it](/customization.md) without a prefix, resulting in a more readable `` component. ```blade @extends('layout') diff --git a/ssr.md b/ssr.md index 3a46ad8..7721d1d 100644 --- a/ssr.md +++ b/ssr.md @@ -18,7 +18,7 @@ By running `npm run build`, Vite will build the SSR entry point and save it at ` node bootstrap/ssr/ssr.mjs ``` -By default, it starts on port 9000, but you may choose another port. Don't forget to update the port in the `splade.php` configuration file. +By default, it starts on port 9000, but you may choose another port. Don't forget to update the port in the `splade.php` [configuration file](/customization.md). ```bash node bootstrap/ssr/ssr.js --port=4242 diff --git a/title-meta.md b/title-meta.md index 2dcd008..27ee190 100644 --- a/title-meta.md +++ b/title-meta.md @@ -24,7 +24,7 @@ The `keywords` method accepts an array as well: SEO::keywords(['laravel', 'splade', 'course']); ``` -In the `splade.php` configuration file, you may set the default content: +In the `splade.php` [configuration file](/customization.md), you may set the default content: ```php return [ diff --git a/x-flash.md b/x-flash.md index 36b3210..3b55b71 100644 --- a/x-flash.md +++ b/x-flash.md @@ -9,4 +9,4 @@ You may use the **Flash Component** to interact with [Flash Data](https://larave ``` > **Warning** -> By default, Splade will share *all* Flash Data to the frontend. You may disable this behavior with the `splade.share_session_flash_data` configuration key. +> By default, Splade will share *all* Flash Data to the frontend. You may disable this behavior with the `splade.share_session_flash_data` [configuration key](/customization.md). From d29686919c63174bce96cb625d164b78fcd2e0da Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Mon, 17 Oct 2022 10:02:42 +0200 Subject: [PATCH 007/121] Update x-form.md --- x-form.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/x-form.md b/x-form.md index 98a6ab4..f7b5752 100644 --- a/x-form.md +++ b/x-form.md @@ -10,6 +10,8 @@ The **Form Component** allows you to send forms asynchronously. This way, you'll ``` +The example above uses regular HTML form inputs, but Splade also comes with a collection of feature-rich [Form Components](/form-overview.md). These components all support labels, validation, data-binding, are more. + ## Method and Validation errors Just like traditional forms, there's a `method` attribute. In addition, you may use the `form.errors` prop to evaluate validation errors: @@ -119,9 +121,17 @@ Similarly, there's a `form.restore` method to restore the default values. ``` +### Prevent navigation on submit + +If you want to stay on the same page after a successful request and want to preserve the page's current state, add the `stay` attribute. + +```blade + +``` + ### Reset and restore on success -If you redirect back to the same page after a successful request and want to preserve the page's current state, add the `stay` attribute. You may choose to reset or restore the form data automatically. You can do this with the `reset-on-success` and `restore-on-success` attributes: +You may choose to reset or restore the form data automatically. You can do this with the `reset-on-success` and `restore-on-success` attributes: ```blade From 0d8747fce0d10a809cbc0560224e254eb13a2f5a Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Mon, 17 Oct 2022 13:23:35 +0200 Subject: [PATCH 008/121] Update x-form.md --- x-form.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/x-form.md b/x-form.md index f7b5752..789aa0b 100644 --- a/x-form.md +++ b/x-form.md @@ -99,6 +99,24 @@ You may use the input event to bind the selected file to your form data: The dedicated [File Component](/form-file.md) provides a cleaner solution, and has support for selecting multiple files as well as displaying the filename of the selected file. +## Submit on change + +Sometimes you want to submit the form whenever a value changes, for example, on a settings page that you want to save immediately. For this, you may use the `submit-on-change` attribute. + +``` + +``` + +You may optionally specify one or more values (with an `array` or `string`) that should be watched, instead of all values. + +``` + + + + + +``` + ## Reset and restore form You may use the `form.reset` method to clear all form data. From d79fa6b20d641a513b28ab698630aa2b50dd877c Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Mon, 17 Oct 2022 13:24:20 +0200 Subject: [PATCH 009/121] Update x-form.md --- x-form.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-form.md b/x-form.md index 789aa0b..8afef70 100644 --- a/x-form.md +++ b/x-form.md @@ -103,13 +103,13 @@ The dedicated [File Component](/form-file.md) provides a cleaner solution, and h Sometimes you want to submit the form whenever a value changes, for example, on a settings page that you want to save immediately. For this, you may use the `submit-on-change` attribute. -``` +```blade ``` -You may optionally specify one or more values (with an `array` or `string`) that should be watched, instead of all values. +In addition, you may optionally specify one or more values (with an `array` or `string`) that Splade should watch instead of all values. -``` +```blade From a084651c09d12546b2a8afb637df8480ccee2230 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 18 Oct 2022 12:14:33 +0200 Subject: [PATCH 010/121] Preserve scroll position --- navigation-routing.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/navigation-routing.md b/navigation-routing.md index 9702bfb..3dc27a9 100644 --- a/navigation-routing.md +++ b/navigation-routing.md @@ -17,4 +17,24 @@ Now when you use the `` component, Splade will prevent a full page reload Visit contact page ``` -You may also configure Splade to transform all `` elements as described in the [Link Component section](/x-link.md). \ No newline at end of file +You may also configure Splade to transform all `` elements as described in the [Link Component section](/x-link.md). + +## Preserve scroll position + +When the user navigates through the app, the browser will reset the scroll position of scrollable elements. In some cases, this might not be a great user experience. + +One example is a sidebar menu that's taller than the window height and thus has a vertical scroll bar. When a user clicks on a menu item in the bottom section and Splade navigates to the next page, you probably want to preserve the scroll position of the sidebar menu. + +You may use the `@preserveScroll` directive on an element to tell Splade to keep track of the scroll position. Be sure to pass a unique name to the directive: + +```blade +
+
+ {{-- scrolling menu --}} +
+ +
+ {{-- content --}} +
+
+``` \ No newline at end of file From e0642431c5bb61ab77b4864e7c5b0129868a56d2 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 18 Oct 2022 12:16:01 +0200 Subject: [PATCH 011/121] Update navigation-routing.md --- navigation-routing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/navigation-routing.md b/navigation-routing.md index 3dc27a9..4bc8ce6 100644 --- a/navigation-routing.md +++ b/navigation-routing.md @@ -23,7 +23,7 @@ You may also configure Splade to transform all `
` elements as described in th When the user navigates through the app, the browser will reset the scroll position of scrollable elements. In some cases, this might not be a great user experience. -One example is a sidebar menu that's taller than the window height and thus has a vertical scroll bar. When a user clicks on a menu item in the bottom section and Splade navigates to the next page, you probably want to preserve the scroll position of the sidebar menu. +One example is a sidebar menu that's taller than the window height and thus has a vertical scrollbar. When a user clicks on a menu item in the bottom section and Splade navigates to the next page, you probably want to preserve the scroll position of the sidebar menu. You may use the `@preserveScroll` directive on an element to tell Splade to keep track of the scroll position. Be sure to pass a unique name to the directive: From 51957c96202fe24fd81a4f185642358c23f6a602 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 18 Oct 2022 20:44:49 +0200 Subject: [PATCH 012/121] Update persistent-layout.md --- persistent-layout.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/persistent-layout.md b/persistent-layout.md index fe52aad..e33b3b5 100644 --- a/persistent-layout.md +++ b/persistent-layout.md @@ -4,6 +4,8 @@ When Splade performs a page load, Vue will, under the hood, rerender the page an Luckily, Splade lets you use a Persistent Layout. So, instead of documenting all options, let's build the example with the media player step-by-step. + + ## Make a Layout Create a new Blade Component using the Laravel Artisan CLI. You can read more about building Layouts with Blade Components in the [Laravel documentation](https://laravel.com/docs/9.x/blade#layouts-using-components). From ab49c8642dab2303d004d0bdfc339c5149fcf55b Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 18 Oct 2022 20:55:02 +0200 Subject: [PATCH 013/121] Fixes #21 --- toasts.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/toasts.md b/toasts.md index 6c7a95c..ebe4d49 100644 --- a/toasts.md +++ b/toasts.md @@ -31,4 +31,23 @@ Toast::title('Whoops!') ->leftTop() ->backdrop() ->autoDismiss(15); -``` \ No newline at end of file +``` + +You may also pass a text value directly to the *position* and *style* methods: + +```php +Toast::warning('No space left!'); + +Toast::center('Welcome back!'); +``` + +## Default Toast settings + +You may customize the default settings using the `Splade` facade, for example, in the `AppServiceProvider` class: + +```php +Splade::defaultToast(function ($toast) { + $toast->info()->leftBottom()->autoDismiss(10); +}); +``` + From 59601bce5c27dbacb760fc45585b83df95370902 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 18 Oct 2022 20:58:50 +0200 Subject: [PATCH 014/121] Fixes #16 --- table-query-builder.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/table-query-builder.md b/table-query-builder.md index 8f54c62..76528ac 100644 --- a/table-query-builder.md +++ b/table-query-builder.md @@ -1,4 +1,4 @@ -# Table built-in Query Builder +# Table with the built-in Query Builder Besides rendering the head, body, and pagination, the component supports many other features like filtering, searching, sorting, and more. @@ -143,7 +143,7 @@ When using auto-fill, you may want to transform the presented data for a specifi ```blade - Edit + Edit ``` @@ -152,7 +152,7 @@ If you want to change the `$item` variable, you may use use the `as` attribute o ```blade - Edit + Edit ``` @@ -163,7 +163,7 @@ This is a *scoped* component, so variables outside the slot won't be available b

{{ $message }}

- Edit + Edit
``` @@ -176,11 +176,13 @@ When your template uses multiple custom cells, you may set these variables as de - Edit + Edit ``` +*Note the `modal` attribute on the Link element in the example above. Instead of navigating to another page, you may open a [Modal or Slideover](/x-modal.md) from a Table. + ## Row Link You may use the `rowLink` method to make one entire row clickable. From 59fec03b8349aa9ad2a76a030d94af29b634e57f Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 18 Oct 2022 20:59:18 +0200 Subject: [PATCH 015/121] Update table-query-builder.md --- table-query-builder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/table-query-builder.md b/table-query-builder.md index 76528ac..3cb26d0 100644 --- a/table-query-builder.md +++ b/table-query-builder.md @@ -181,7 +181,7 @@ When your template uses multiple custom cells, you may set these variables as de ``` -*Note the `modal` attribute on the Link element in the example above. Instead of navigating to another page, you may open a [Modal or Slideover](/x-modal.md) from a Table. +*Note the `modal` attribute on the Link element in the example above. Instead of navigating to another page, you may open a [Modal or Slideover](/x-modal.md) from a Table.* ## Row Link From d1ff7b4a9eb1547e1d1c90ff9c6d6e30562cad84 Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Tue, 18 Oct 2022 23:29:08 +0200 Subject: [PATCH 016/121] Create splade-vs-inertia.md --- splade-vs-inertia.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 splade-vs-inertia.md diff --git a/splade-vs-inertia.md b/splade-vs-inertia.md new file mode 100644 index 0000000..6606467 --- /dev/null +++ b/splade-vs-inertia.md @@ -0,0 +1,38 @@ +# Splade and Inertia.js comparison + +Splade and Inertia.js share many features and goals but are fundamentally different. This overview is definitely **not** intended to disregard Inertia.js in any way but even more to help you choose a direction for your next application. + +## Template engine + +The key difference between Splade and Inertia.js is the template engine and how you pass data to templates. While Splade lets you combine the power of the Blade and the Vue template engine, Inertia.js templates should be written in React, Vue, or Svelte, in addition to requiring a backend framework like Laravel. + +To summarize: +* Splade allows you to use the Laravel Blade template engine and build a single-page application using regular server-side routing without building an API. +* Inertia.js requires a separate frontend *and* backend framework and acts as a bridge between them. It's framework agnostic, so you may use frameworks other than Laravel and Vue, like Rails and React. + +## Passing data + +Passing data from the Controller to templates is handled very differently. With Inertia.js, **all data** you pass from the Controller to a template will be available client-side (in the browser). Of course, you may use a transformation layer (like [Fractal](https://fractal.thephpleague.com) or Laravel's [API Resources](https://laravel.com/docs/9.x/eloquent-resources)), but you still have to worry about the data size and not sharing sensitive data with the browser. + +In Splade applications, almost all data is rendered using standard server-side Blade templates. Once rendered in Blade, the raw data won't be available client-side (in the browser). Of course, you may pass data to the frontend, for example, with the [Data](/x-data.md) and [Form](/x-form.md) components, but that’s very explicit. The Form component even helps you guard data against being passed to the browser. + +Another inconvenience in development with Inertia.js + Vue is having to define the data and properties twice. First, you pass the data from the Controller, and then you *also* have to explicitly specify the data client-side, for example, in the `props` declaration of the Vue template. With Splade, you can use the data directly in the Blade template without defining it. + +To summarize: +* With Inertia.js, you should be very aware that every piece of data you return from the Controller will be visible client-side. +* This is less of a concern with Splade, as almost everything is rendered server-side, and most raw data will never leave the application. +* In every application, and also with Splade, there are cases where you still want to pass data to the frontend. Splade provides components to help you do this. +* Besides returning the server-side, with Inertia.js + Vue, you must also define the data as props *again* in the front-end template. This is not needed with Splade. + +## Laravel integration + +Splade aims to stick as close as possible to the default Laravel features and development flow: + +* You don't need a *special* method in Controller methods, like `Inertia::render()`. With Splade, you can use Laravel's `view()` method. +* You don't need to make your route definitions available to the frontend in order to generate URLs in templates. Inertia.js recommends the Ziggy library for this. With Splade, you can use Laravel's `route()` method and `Route` facade. +* You don't need to modify a Middleware class or use a dedicated method like `Inertia::share()` to pass flash or shared data to templates. With Splade, you can use Laravel's `session()->flash()` and `View::share()` methods. + +## Misc + +* Besides using 3rd-party Vue libraries, Splade allows you to use Laravel packages with Blade components and directives. For example, you can use the [Blade Icons](https://blade-ui-kit.com/blade-icons) package in your application. +* Inertia.js is framework agnostic, and while that’s a great foundation, it also seems to slow down development. Splade focuses on Laravel and Vue and can fully integrate with both without worrying about compatibility and cross-platform implementation challenges. \ No newline at end of file From 3ee97565c04692700341f76892f8295abda58e7f Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Tue, 18 Oct 2022 23:36:07 +0200 Subject: [PATCH 017/121] Update splade-vs-inertia.md --- splade-vs-inertia.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/splade-vs-inertia.md b/splade-vs-inertia.md index 6606467..87f0655 100644 --- a/splade-vs-inertia.md +++ b/splade-vs-inertia.md @@ -16,13 +16,13 @@ Passing data from the Controller to templates is handled very differently. With In Splade applications, almost all data is rendered using standard server-side Blade templates. Once rendered in Blade, the raw data won't be available client-side (in the browser). Of course, you may pass data to the frontend, for example, with the [Data](/x-data.md) and [Form](/x-form.md) components, but that’s very explicit. The Form component even helps you guard data against being passed to the browser. -Another inconvenience in development with Inertia.js + Vue is having to define the data and properties twice. First, you pass the data from the Controller, and then you *also* have to explicitly specify the data client-side, for example, in the `props` declaration of the Vue template. With Splade, you can use the data directly in the Blade template without defining it. +Another inconvenience in development with Inertia.js + Vue is having to define the data and properties twice. First, you pass the data from the Controller, and then you *also* have to explicitly specify the data client-side in the `props` declaration of the Vue template. With Splade, you can use the data directly in the Blade template without defining it. To summarize: * With Inertia.js, you should be very aware that every piece of data you return from the Controller will be visible client-side. * This is less of a concern with Splade, as almost everything is rendered server-side, and most raw data will never leave the application. * In every application, and also with Splade, there are cases where you still want to pass data to the frontend. Splade provides components to help you do this. -* Besides returning the server-side, with Inertia.js + Vue, you must also define the data as props *again* in the front-end template. This is not needed with Splade. +* Besides returning the data server-side, with Inertia.js + Vue, you must also define the data as props *again* in the front-end template. This is not needed with Splade. ## Laravel integration From 27cf5b712a6a7da873ca58f1a87a18040a5f376d Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 19 Oct 2022 10:43:22 +0200 Subject: [PATCH 018/121] Update persistent-layout.md --- persistent-layout.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/persistent-layout.md b/persistent-layout.md index e33b3b5..fb0b3d5 100644 --- a/persistent-layout.md +++ b/persistent-layout.md @@ -1,3 +1,8 @@ +--- +description: Laravel Splade lets you use a Persistent Layout with Blade. One example is a media player that must continue playing while your users navigate from one page to the next. +keywords: laravel persistent layout, blade persistent layout, splade persistent layout, persistent layout, persistent layouts +--- + # Persistent Layout When Splade performs a page load, Vue will, under the hood, rerender the page and its components. While it's clever enough to minimize the performance impact and thus give you a seamless *SPA*-experience, it will also rerender elements you might want to keep alive. The most common example is a media player that must continue playing while your users navigate your app. From 135c299b7d5b732fdf396f9dfee8d382f2250ebe Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 19 Oct 2022 11:37:09 +0200 Subject: [PATCH 019/121] SEO --- table-bulk-actions.md | 5 +++++ table-exports.md | 5 +++++ table-overview.md | 5 +++++ using-vue-libraries.md | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/table-bulk-actions.md b/table-bulk-actions.md index 44520d6..06e71a4 100644 --- a/table-bulk-actions.md +++ b/table-bulk-actions.md @@ -1,3 +1,8 @@ +--- +description: The Splade Table component supports Bulk Actions. It can perform the action on the selected rows, on all rows on the current page, or on all rows on all pages. +keywords: laravel datatables bulk actions, laravel datatables actions, laravel table bulk action, laravel tables bulk action +--- + # Table Bulk Actions The Table component supports performing Bulk Actions. First, you must register a supporting route using the `spladeTable()` method on the `Route` facade. As of version 0.6, the automatic installer does this for you. If you need to register the route manually, make sure it uses the `web` and `splade` Middleware, for example, in `web.php`: diff --git a/table-exports.md b/table-exports.md index bd79b26..bc0075b 100644 --- a/table-exports.md +++ b/table-exports.md @@ -1,3 +1,8 @@ +--- +description: The Splade Table component supports exporting to Excel, CSV, PDF, and other formats. You may enable exporting with the export() method, which will configure an Excel Export by default. +keywords: laravel datatables excel export, laravel datatables pdf export, laravel table export, laravel tables export +--- + # Table Exports The Table component supports Exports. But first, you must register a supporting route using the `spladeTable()` method on the `Route` facade. As of version 0.6, the automatic installer does this for you. If you need to register the route manually, make sure it uses the `web` and `splade` Middleware, for example, in `web.php`: diff --git a/table-overview.md b/table-overview.md index f4c8abe..035e049 100644 --- a/table-overview.md +++ b/table-overview.md @@ -1,3 +1,8 @@ +--- +description: Splade has an advanced Table component that supports auto-fill, searching, filtering, sorting, toggling columns, and pagination. You may also perform bulk actions and exports. +keywords: laravel datatable, laravel datatables, laravel table, laravel table component, laravel tables +--- + # Table (DataTables) Component Splade has an advanced Table component that supports auto-fill, searching, filtering, sorting, toggling columns, and pagination. You may also perform bulk actions and exports. Though optional, it integrates beautifully with Spatie's [Laravel Query Builder](https://github.com/spatie/laravel-query-builder). diff --git a/using-vue-libraries.md b/using-vue-libraries.md index ed6969d..d989e34 100644 --- a/using-vue-libraries.md +++ b/using-vue-libraries.md @@ -1,3 +1,8 @@ +--- +description: You may Vue libraries in a Laravel Splade app by install the library using npm, and then import and register it in the main app.js file. You must import and register the component by passing both a name string and a component definition. +keywords: laravel blade vue, laravel vue blade, laravel vue library, laravel vue libraries +--- + # Using Vue libraries Using Vue libraries in a Splade app works the same as any other Vue application. You may install the library using `npm`, and then import and register it in the main `app.js` file. If you're using [SSR](/ssr.md), make sure to import the component in `ssr.js` as well. From 9189dda1bf8b254f05e91583345209e7730e8810 Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Thu, 20 Oct 2022 13:59:59 +0200 Subject: [PATCH 020/121] Typos --- automatic-installation.md | 2 +- form-select.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/automatic-installation.md b/automatic-installation.md index 0325d50..2b8853a 100644 --- a/automatic-installation.md +++ b/automatic-installation.md @@ -1,6 +1,6 @@ # Automatic Installation -A fresh Laravel application is an ideal way to get started with Splade. The package provides a convenient Artisan command, which installs [Tailwind CSS 3.0](https://tailwindcss.com) and [Vue 3.0](https://vuejs.org) on the frontend. On the backend, it installs a Route Middleware, an Exception Handler, and it prepares a default view and with its route. +A fresh Laravel application is an ideal way to get started with Splade. The package provides a convenient Artisan command, which installs [Tailwind CSS 3.0](https://tailwindcss.com) and [Vue 3.0](https://vuejs.org) on the frontend. On the backend, it installs a Route Middleware, an Exception Handler, and it prepares a default view and its route. ```bash laravel new example-app diff --git a/form-select.md b/form-select.md index e9646a3..95ba944 100644 --- a/form-select.md +++ b/form-select.md @@ -75,7 +75,7 @@ Now you may add the `choices` attribute to the component: It works for selecting multiple values as well: ```blade - + ``` You can instantiate Choices.js with a [custom set of options](https://github.com/Choices-js/Choices#setup) by passing a *JavaScript* object to the `choices` attribute. To pass a PHP array, you may use the `:choices` attribute (note the colon). From 6aded1bd4445649252aa28081d0c892cabe7428c Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 20 Oct 2022 19:39:06 +0200 Subject: [PATCH 021/121] Update form-checkbox.md --- form-checkbox.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/form-checkbox.md b/form-checkbox.md index 0a7ac85..816e2b1 100644 --- a/form-checkbox.md +++ b/form-checkbox.md @@ -1,9 +1,15 @@ # X-Splade-Checkbox Component -The **Checkbox Component** has a default value of `1`, but you may customize it with the `value` attribute: +The **Checkbox Component** has a default value of `true`, but you may customize it with the `value` attribute: ```blade - + +``` + +The default `true` value works great if you use the `boolean` type [Attribute Casting](https://laravel.com/docs/9.x/eloquent-mutators#attribute-casting) in Eloquent Models. Accordingly, the *unchecked* value is `false`, but you may customize it with the `false-value` attribute: + +```blade + ``` If you have a fieldset of multiple checkboxes, you can group them with the `x-splade-group` component. A group is a great way to handle the validation of arrays. If you disable the errors on the individual checkboxes, it will show the validation errors once. The [group component](/form-group.md) has a `show-errors` attribute that defaults to `true`. From 391c9a4e839eb2ee3e0977fd9db76e388e4601a5 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Sun, 23 Oct 2022 23:29:31 +0200 Subject: [PATCH 022/121] Update navigation-routing.md --- navigation-routing.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/navigation-routing.md b/navigation-routing.md index 4bc8ce6..a304471 100644 --- a/navigation-routing.md +++ b/navigation-routing.md @@ -37,4 +37,22 @@ You may use the `@preserveScroll` directive on an element to tell Splade to keep {{-- content --}} +``` + +## Redirects + +Splade automatically handles redirects, both internally and externally. The default Laravel redirect methods just work: + +```php +return redirect('home/dashboard'); + +return redirect()->route('profile', ['id' => 1]); + +return redirect()->away('https://www.google.com/'); +``` + +Splade detects when you redirect to an external domain outside of your app. You may use Laravel's [built-in](https://laravel.com/docs/9.x/responses#redirecting-external-domains) `away()` method on the `redirect()` helper method. Still, you may also use the `redirectAway()` method on the Splade facade to explicitly tell Splade to redirect away from the app: + +```php +return Splade::redirectAway('https://www.google.com/'); ``` \ No newline at end of file From d3e6a938b5df7ab62951148e20e798cb6c80fcd1 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Sun, 23 Oct 2022 23:48:59 +0200 Subject: [PATCH 023/121] Update x-link.md --- x-link.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/x-link.md b/x-link.md index 442af4d..e5da6fe 100644 --- a/x-link.md +++ b/x-link.md @@ -27,6 +27,14 @@ In addition, you may customize the confirmation dialog: ``` +## Redirecting To External Domains + +When the URL is outside your application pointing to an external domain, you'd typically use a regular `` element. Still, you may use the `away` attribute on the `Link` component. This can be useful when you have wrapped the component into another component and don't want to change the tag dynamically. + +```blade +Google +``` + ## Transform all anchors If you don't want to use the `Link` component but want Splade to transform all `` elements, you need to update the plugin options in the `app.js` file: From 422fa8118ab978385a5475d0c7c23aa8bb2838d6 Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Mon, 24 Oct 2022 10:58:55 +0200 Subject: [PATCH 024/121] Create index.json --- index.json | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 index.json diff --git a/index.json b/index.json new file mode 100644 index 0000000..5256bb1 --- /dev/null +++ b/index.json @@ -0,0 +1,64 @@ +{ + "Introduction": { + "Introducing Splade": "introducing-splade", + "Credits": "credits", + "Automatic installation": "automatic-installation", + "Manual installation": "manual-installation", + "Breeze starter kit": "breeze", + "Upgrading": "upgrading", + "Roadmap": "roadmap", + "Inertia.js comparison": "splade-vs-inertia" + }, + "Basics": { + "Navigation and routing": "navigation-routing", + "Progress bar": "progress-bar", + "Toasts": "toasts", + "Shared data": "shared-data", + "Title and meta tags": "title-meta", + "Lazy loading": "lazy-loading", + "Server-side rendering (SSR)": "ssr" + }, + "Components": { + "Data": "x-data", + "Defer": "x-defer", + "Errors": "x-errors", + "Event": "x-event", + "Flash": "x-flash", + "Form": "x-form", + "Link": "x-link", + "Modal": "x-modal", + "State": "x-state", + "Teleport": "x-teleport", + "Toggle": "x-toggle", + "Transition": "x-transition" + }, + "Form components": { + "Overview": "form-overview", + "Input": "form-input", + "Textarea": "form-textarea", + "Select": "form-select", + "Checkbox": "form-checkbox", + "Radio": "form-radio", + "File": "form-file", + "Group": "form-group", + "Submit": "form-submit", + "Model Binding": "form-model-binding-attributes" + }, + "Table component": { + "Overview": "table-overview", + "Built-in Query Builder": "table-query-builder", + "Bulk Actions": "table-bulk-actions", + "Exports": "table-exports", + "Spatie Query Builder": "table-spatie-query-builder" + }, + "Vue components and libraries": { + "Custom components": "custom-vue-components", + "Vue libraries": "using-vue-libraries" + }, + "Advanced": { + "State management": "state-management", + "Persistent layout": "persistent-layout", + "Customization": "customization", + "How Splade works": "how-splade-works" + } +} \ No newline at end of file From 09aba71c2585c866d233c957a6ced492837dc2e4 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 25 Oct 2022 11:35:28 +0200 Subject: [PATCH 025/121] Update title-meta.md (#23) --- title-meta.md | 97 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 21 deletions(-) diff --git a/title-meta.md b/title-meta.md index 27ee190..f646780 100644 --- a/title-meta.md +++ b/title-meta.md @@ -1,3 +1,8 @@ +--- +description: The SEO facade lets you set the page's title, description, and keywords. You may also set a default prefix/suffix for the title. There are five helper methods to set Open Graph and Twitter tags. +keywords: laravel seo, blade seo, splade seo, splade title, splade description, splade meta, splade meta tags, splade keywords, laravel twitter tags, laravel og tags, laravel open graph tags, laravel twitter meta, laravel og meta, laravel open graph meta +--- + # Title and meta tags You may use the `SEO` facade to set your page's title, description, and keywords. @@ -24,50 +29,100 @@ The `keywords` method accepts an array as well: SEO::keywords(['laravel', 'splade', 'course']); ``` -In the `splade.php` [configuration file](/customization.md), you may set the default content: +You may publish and customize the `splade-seo.php` configuration file to set default values. In previous versions of Splade, the SEO configuration was part of the `splade.php` configuration file. As of v0.7, there is a separate file for the SEO configuration. + +```bash +php artisan vendor:publish --provider="ProtoneMedia\Splade\ServiceProvider" --tag="seo" +``` ```php return [ - ... + 'defaults' => [ + 'title' => 'My application', - 'seo' => [ - 'defaults' => [ - 'title' => 'My application', + 'description' => 'This is the description of my application.', - 'description' => 'This is the description of my application.', - - 'keywords' => ['application', 'keywords'], - ], + 'keywords' => ['application', 'keywords'], ], - - ... ]; ``` -You may also set a default prefix/suffix for the title. With the example below, if you call `SEO::setTitle('Home')`, the final title will become `Page: Home | My app`. +You may also set a default prefix, suffix and separator for the title. With the example below, if you call `SEO::setTitle('Home')`, the final title will become `Home | My app`. ```php return [ - ... + 'title_separator' => '|', - 'seo' => [ - 'title_prefix' => 'Page:', + 'title_suffix' => 'My app', +]; +``` - 'title_suffix' => '| My app', - ] +## Canonical URL - ``` -]; +By default, the canonical URL is set to the current URL, but you may override it with the `canonical` method: + +```php +SEO::canonical('https://splade.dev/'); ``` -There are three additional methods to set other meta tags. You can set meta tags by name, property, or by giving a custom set of attributes. Future releases of Splade will include additional helper methods to set OpenGraph and other SEO tags. +Suppose you don't want to automatically set the canonical URL to the current URL. You may disable this in the `splade-seo.php` config file by setting the `auto_canonical_link` key to `false`. + +## Open Graph tags + +There are five helper methods to set Open Graph tags: ```php -SEO::metaByName('twitter:site', '@pascalbaljet'); +SEO::openGraphType('WebPage'); +SEO::openGraphSiteName('My Application'); +SEO::openGraphTitle('Home Page'); +SEO::openGraphUrl('https://my.app/home'); +SEO::openGraphImage(public_path('home.png')); +``` + +In the `splade-seo.php` configuration file, you may set default values and an `auto_fill` option. When you set this option to `true`, the value passed to the `SEO::title()` method will also be applied to the Open Graph Title tag. + +## Twitter tags + +There are five helper methods to set Twitter tags: + +```php +SEO::twitterCard('summary_large_image'); +SEO::twitterSite('@pascalbaljet'); +SEO::twitterTitle('Home Page | My App'); +SEO::twitterDescription('This is the home page of my application'); +SEO::twitterImage(public_path('home.png')); +``` + +In the `splade-seo.php` configuration file, you may set default values and an `auto_fill` option. When you set this option to `true`, values passed to `SEO::title()` and `SEO::description()` methods will also be applied to the corresponding Twitter tags. + +## Custom Meta Tags + +There are three additional methods to set other meta tags. You can set meta tags by name, property, or by giving a custom set of attributes. + +```php +SEO::metaByName('theme-color', '#ffffff'); SEO::metaByProperty('article:section', 'news'); SEO::meta([ 'custom-attribute' => 'example' ]); +``` + +## SEO Macro + +The underlying class of the `SEO` facade uses Laravel's `Macroable` trait, so it's easy to add a method: + +```php +SEO::macro('openGraphLocale', function (string $value) { + return $this->metaByProperty('og:locale', $value); +}); +``` + +Make sure to return from the callback, so you may use the facade fluently: + +```php +SEO::title('Laravel Splade Cursus') + ->openGraphLocale('nl') + ->description('Wil je een Splade expert worden?'); ``` \ No newline at end of file From 8b89f3b6fdabf223de057e63ebd7241cd58056d0 Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Tue, 25 Oct 2022 11:38:32 +0200 Subject: [PATCH 026/121] Update lazy-loading.md --- lazy-loading.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lazy-loading.md b/lazy-loading.md index 0e0acc8..a97c6c8 100644 --- a/lazy-loading.md +++ b/lazy-loading.md @@ -12,6 +12,8 @@ The **Lazy Component** allows you to load sections of your template lazily. Wrap ``` + + ## Lazy View Data While excluding a section from your template is nice, you probably also want to exclude data from the initial page load. Most commonly, this is the data you need in your lazily loaded content. You may use the `onInit` and `onLazy` methods on the `Splade` facade to wrap the data in a closure. From 9081ec2d5d2c273a01280ca80427528baa2fdc02 Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Tue, 25 Oct 2022 11:38:59 +0200 Subject: [PATCH 027/121] Update title-meta.md --- title-meta.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/title-meta.md b/title-meta.md index f646780..9fadcb1 100644 --- a/title-meta.md +++ b/title-meta.md @@ -29,7 +29,7 @@ The `keywords` method accepts an array as well: SEO::keywords(['laravel', 'splade', 'course']); ``` -You may publish and customize the `splade-seo.php` configuration file to set default values. In previous versions of Splade, the SEO configuration was part of the `splade.php` configuration file. As of v0.7, there is a separate file for the SEO configuration. +You may publish and customize the `splade-seo.php` configuration file to set default values. In previous versions of Splade, the SEO configuration was part of the `splade.php` configuration file. As of v0.6.9, there is a separate file for the SEO configuration. ```bash php artisan vendor:publish --provider="ProtoneMedia\Splade\ServiceProvider" --tag="seo" From 8eaf707b1cd61755c35866c06a230c632d0613d7 Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Tue, 25 Oct 2022 11:41:03 +0200 Subject: [PATCH 028/121] Update title-meta.md --- title-meta.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/title-meta.md b/title-meta.md index 9fadcb1..fc4b051 100644 --- a/title-meta.md +++ b/title-meta.md @@ -95,7 +95,7 @@ SEO::twitterImage(public_path('home.png')); In the `splade-seo.php` configuration file, you may set default values and an `auto_fill` option. When you set this option to `true`, values passed to `SEO::title()` and `SEO::description()` methods will also be applied to the corresponding Twitter tags. -## Custom Meta Tags +## Custom meta tags There are three additional methods to set other meta tags. You can set meta tags by name, property, or by giving a custom set of attributes. From 2a392198d64122b74588aa865494eb8493e7c162 Mon Sep 17 00:00:00 2001 From: pascalbaljet Date: Tue, 25 Oct 2022 14:25:22 +0200 Subject: [PATCH 029/121] Update table-query-builder.md --- table-query-builder.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/table-query-builder.md b/table-query-builder.md index 3cb26d0..2e1e9fb 100644 --- a/table-query-builder.md +++ b/table-query-builder.md @@ -66,7 +66,7 @@ By default, the `canBeHidden` value is set to `true`, making every column toggle SpladeTable::defaultColumnCanBeHidden(false); ``` -The `searchable` boolean is a shortcut to the `searchInput` method. The example below will essentially call `$table->searchInput('name', 'User Name')`. +The `searchable` boolean is a shortcut to the `searchInput` method. The example above will essentially call `$table->searchInput('name', 'User Name')`. ### Default sort @@ -78,7 +78,7 @@ $table->defaultSort('name'); ### Sort by Relationship column -The Table supports sorting the results by a [Relationship](https://laravel.com/docs/9.x/eloquent-relationships) column. This requires the installation of the [`kirschbaum-development/eloquent-power-joins`](https://github.com/kirschbaum-development/eloquent-power-joins) package. +The Table component supports sorting the results by a [Relationship](https://laravel.com/docs/9.x/eloquent-relationships) column. This requires the installation of the [`kirschbaum-development/eloquent-power-joins`](https://github.com/kirschbaum-development/eloquent-power-joins) package. ```php $table->column( From 25b084935a9e68cd90e6eabb5948446caeceda1e Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 1 Nov 2022 11:20:49 +0100 Subject: [PATCH 030/121] Content Component (#24) --- index.json | 1 + x-content.md | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 x-content.md diff --git a/index.json b/index.json index 5256bb1..b7968a1 100644 --- a/index.json +++ b/index.json @@ -19,6 +19,7 @@ "Server-side rendering (SSR)": "ssr" }, "Components": { + "Content": "x-content", "Data": "x-data", "Defer": "x-defer", "Errors": "x-errors", diff --git a/x-content.md b/x-content.md new file mode 100644 index 0000000..09b50a0 --- /dev/null +++ b/x-content.md @@ -0,0 +1,13 @@ +# X-Splade-Content Component + +All templates are passed to the Vue render engine. Still, sometimes you want to output raw, pre-rendered HTML, and you might want to bypass Vue's interpolation using the **Content Component**. A typical example is pre-rendered Markdown content. Note that the content is static, and you can't pass Splade or Vue components. + +```blade + +``` + +By default, the element is rendered as a `div`, but you may customize it, as well as pass other attributes: + +```blade + +``` \ No newline at end of file From b306d184cceffc89aa6d50d0c25ee76d1090ebb2 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 3 Nov 2022 09:55:56 +0100 Subject: [PATCH 031/121] Remote select options (#25) --- form-select.md | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/form-select.md b/form-select.md index 95ba944..101cfe8 100644 --- a/form-select.md +++ b/form-select.md @@ -1,6 +1,6 @@ # X-Splade-Select Component -The **Select Component** can render the options based on an array, with support for groups. +The **Select Component** can render the options based on a *key-value* array or `Collection`, with support for groups. ```php $countries = [ @@ -13,6 +13,12 @@ $countries = [ ``` +You may also pass a set of objects, like an Eloquent Collection, and specify the *value* and *label* keys for the option elements: + +```blade + +``` + You can provide a slot to the select element as well: ```blade @@ -104,6 +110,29 @@ Select::defaultChoices([ ]); ``` +### Remote Options + +The component has support for loading the options using an asynchronous *ajax* request. For this, you may use the `remote-url` attribute: + +```blade + +``` + +Just like the regular pre-defined options, it supports objects as well: + +```blade + +``` + +The `remote-url` attribute supports *Template literals*, making it perfect for building dependent selects: + +```blade + + +``` + +When the user selects a country, it will reload the regions based on the chosen country. All remote options features work with the Choices.js integration as well. It doesn't support groups yet, but that's coming in a future version of Splade. + ### Customize Choices.js styling Choices.js uses a *SCSS* stylesheet to style the library. Our stylesheet extends the vendor stylesheet (of Choices.js) and adds some Tailwind-specific tweaks. Make sure your bundler handles SCSS stylesheets correctly, for example, by installing `sass`. The `splade:publish-form-stylesheets` Artisan command copies the stylesheet to the `resources` directory of your app. From 164baa8a13f3b88a6ec935e115f9639d0c47457c Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Mon, 14 Nov 2022 22:17:44 +0100 Subject: [PATCH 032/121] Update x-modal.md (#26) --- x-modal.md | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/x-modal.md b/x-modal.md index e7e0997..74a4fe2 100644 --- a/x-modal.md +++ b/x-modal.md @@ -1,8 +1,8 @@ # X-Splade-Modal Component -With the **Modal Component**, Splade has built-in support for modals and slideover. This component allows you to load *any* route into a modal. To prepare a view so you can use it inside a modal, you have to wrap the content in a `` component. Nothing changes when requesting the view *outside* of the modal. Everything will work as it used to be. +With the **Modal Component**, Splade has built-in support for modals and slideover. This component allows you to load *any* route into a modal. Besides loading the content asynchronously, it also supports pre-loaded content. -For example, here's a page to create a new user. This page is a regular, full-page view that extends the base layout. +First, let's take a look at loading a route into a modal. To prepare a view to use it inside a modal, you have to wrap the content in a `` component. Nothing changes when requesting the view *outside* of the modal. Everything will work as it used to. For example, here's a page to create a new user. This page is a regular, full-page view that extends the base layout. ```blade @extends('layout') @@ -79,3 +79,32 @@ You can manually close the modal or slideover with the `modal.close()` or `modal ``` +## Pre-loaded content + +Instead of loading the content asynchronously, you may also pass the content along with the page. You may do this by passing a `name` attribute to the component and use the name along with a `#` prefix in the `Link` component: + +```blade +

Tickets & Tour Dates

+ + + Show Refund Information + + + +

...

+
+``` + +To use a slideover, you must put the attribute on the `x-splade-component` instead of the `Link` component. The `max-width` attribute works with pre-loaded content as well. + +```blade +

Tickets & Tour Dates

+ + + Show Refund Information + + + +

...

+
+``` \ No newline at end of file From 261d440b77f2ffea63342334dec6bbc34e4ba609 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Tue, 15 Nov 2022 09:24:00 +0100 Subject: [PATCH 033/121] Update table-query-builder.md --- table-query-builder.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/table-query-builder.md b/table-query-builder.md index 2e1e9fb..19a668f 100644 --- a/table-query-builder.md +++ b/table-query-builder.md @@ -76,6 +76,16 @@ You may configure the default sorting with the `defaultSort()` method: $table->defaultSort('name'); ``` +If you want to sort in descending order, you may prefix the key with a `-` character or use the `defaultSortDesc` method. Alternatively, you may use the `defaultSort` method with an additional second argument: + +```php +$table->defaultSort('-name'); + +$table->defaultSortDesc('name'); + +$table->defaultSort('name', 'desc'); +``` + ### Sort by Relationship column The Table component supports sorting the results by a [Relationship](https://laravel.com/docs/9.x/eloquent-relationships) column. This requires the installation of the [`kirschbaum-development/eloquent-power-joins`](https://github.com/kirschbaum-development/eloquent-power-joins) package. From 4e8b23afc5695fd958b5cefbbd9d3be0cdb6ed74 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 18:43:06 +0100 Subject: [PATCH 034/121] Update table-query-builder.md --- table-query-builder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/table-query-builder.md b/table-query-builder.md index 19a668f..6f3b368 100644 --- a/table-query-builder.md +++ b/table-query-builder.md @@ -1,6 +1,6 @@ # Table with the built-in Query Builder -Besides rendering the head, body, and pagination, the component supports many other features like filtering, searching, sorting, and more. +Besides rendering the head, body, and pagination, the component supports many other features like filtering, searching, sorting, and more. The built-in Query Builder has been tested with MySQL, PostgreSQL and SQLite. ## Search Fields From 2bc93d690ba7044bec4598399a06bba8844e5d4c Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 20:37:40 +0100 Subject: [PATCH 035/121] Filepond (#27) --- form-file.md | 174 +++++++++++++++++++++++++++++++++++++++++++++++++ form-select.md | 2 +- 2 files changed, 175 insertions(+), 1 deletion(-) diff --git a/form-file.md b/form-file.md index 2cdd4c9..cea4bee 100644 --- a/form-file.md +++ b/form-file.md @@ -14,4 +14,178 @@ The component supports selecting multiple files as well by adding the `multiple` +``` + +## FilePond + +The [FilePond](https://pqina.nl/filepond/) integration comes with a default stylesheet which you should import into the main JavaScript file. If you've used the automatic installer, it has already done this for you. + +```js +import "@protonemedia/laravel-splade/dist/style.css"; +import { renderSpladeApp, SpladePlugin } from "@protonemedia/laravel-splade"; +``` + +Now you may add the `filepond` attribute to the component: + +```blade + +``` + +This works for uploading multiple files as well: + +```blade + +``` + +You can instantiate FilePond with a [custom set of options](https://pqina.nl/filepond/docs/api/instance/properties/) by passing a *JavaScript* object to the `filepond` attribute. To pass a PHP array, you may use the `:filepond` attribute (note the colon). + +```blade + + + +``` + +### Image Preview + +FilePond can render a downscaled preview of the selected image by adding the `preview` attribute to the component: + +```blade + +``` + +### Validate type and size + +FilePond supports validating the selected file based on the type and size. To validate the type, you may use the `accept` attribute: + +```blade + +``` + +You may use the `min-size` or `max-size` attribute to validate the file size. You may use both attributes at once as well: + +```blade + +``` + +Please be aware that both features are *client-side* validation. For security reasons, make sure you use [server-side validation](https://laravel.com/docs/9.x/validation#validating-files) as well. + +### Validate images + +FilePond supports validating the dimensions of a selected image. For example, you may use the `min-width` and `min-height` attributes to validate the minimum width and height. Similarly, to validate the maximum width and height, you may use the `max-width` and `max-height` attributes: + +```blade + + + +``` + +If you want to validate against an exact size, you may use the `width` and `height` attributes: + +```blade + +``` + +Alternatively, you may specify a minimum or maximum resolution: + +```blade + + + +``` + +### Asynchronous uploads + +FilePond supports uploading the file to the server before the form is submitted. First, you must register a supporting route using the `spladeUploads()` method on the `Route` facade. As of version 0.7.6, the automatic installer does this for you. If you need to register the route manually, make sure it uses the `web` Middleware, for example, in `web.php`: + +```php +Route::spladeUploads(); +``` + +Next, in the template, add the `server` attribute to the component. From now on, when a user drops a file into the FilePond instance, it will immediately start uploading to the server. + +```blade + +``` + +Splade will store the file in a temporary directory and report the path to the file back to the File component. So when the user submits the form, it will send this path instead of uploading the file. + +There are three ways of handling the temporary upload. First, you may use the `HandleSpladeFileUploads` class, for example, in your controller: + +```php +use Illuminate\Http\Request; +use ProtoneMedia\Splade\FileUploads\HandleSpladeFileUploads; + +public function store(Request $request) +{ + HandleSpladeFileUploads::forRequest($request); + + $request->validate([ + 'photo' => ['required', 'file', 'image'], + ]); + + $path = $request->file('photo')->store('images'); +} +``` + +The `HandleSpladeFileUploads` class will loop through the request data and transform paths to temporary uploads back into `UploadedFile` instances. Make sure you call the `forRequest()` method *before* validating the request. Instead of looping through all request data, you may also pass the key (or an array of keys): + +```php +HandleSpladeFileUploads::forRequest($request, 'photo'); +``` + +The second option is to use a Route Middleware. You may use the same `HandleSpladeFileUploads` class as the example above. Using the *fully qualified class name* will loop through all request data, but you may also specify one or more keys using the static `for` method. + +```php +Route::post('podcast', StorePodcastController::class) + ->middleware(HandleSpladeFileUploads::class); + +Route::post('podcast', StorePodcastController::class) + ->middleware(HandleSpladeFileUploads::for('photo')); +``` + +The last option is to use [Form Request](https://laravel.com/docs/9.x/validation#form-request-validation). Then, you only have to implement the `HasSpladeFileUploads` interface and use the `file` validation rule. Splade will automatically extract the keys from the rules. + +```php +use Illuminate\Foundation\Http\FormRequest; +use ProtoneMedia\Splade\FileUploads\HasSpladeFileUploads; + +class StorePodcastRequest extends FormRequest implements HasSpladeFileUploads +{ + public function rules() + { + return [ + 'photo' => 'required|file|image', + ]; + } +} +``` + +### Custom temporary directory + +By default, Splade uses the `/storage/splade-temporary-file-uploads` directory for temporary uploads. If you want to use a custom [Filesystem disk](https://laravel.com/docs/9.x/filesystem#configuration), you may update the `file_uploads.disk` key in the `splade.php` [configuration file](/customization.md). For now, it only supports local disks. + +### Cleanup temporary uploads + +It may happen that temporarily uploaded files are not being used and will fill the temporary directory. Splade comes with a built-in Artisan command to delete all files that are older than one hour: + +```bash +php artisan splade:cleanup-uploads +``` + +You may change the lifetime of temporary files with the `file_uploads.temporary_file_lifetime` key in the `splade.php` [configuration file](/customization.md). + +### Customize FilePond styling + +FilePond uses an *SCSS* stylesheet to style the library. Our stylesheet extends the vendor stylesheet (of FilePond) and adds some Tailwind-specific tweaks. Make sure your bundler handles SCSS stylesheets correctly, for example, by installing `sass`. The `splade:publish-form-stylesheets` Artisan command copies the stylesheet to the `resources` directory of your app. + +```bash +npm install sass -D + +php artisan splade:publish-form-stylesheets +``` + +Then import the stylesheet in your main JavaScript file (instead of the default `@protonemedia/laravel-splade/dist/style.css` stylesheet): + +```js +import "../css/filepond.scss" ``` \ No newline at end of file diff --git a/form-select.md b/form-select.md index 101cfe8..d1c7026 100644 --- a/form-select.md +++ b/form-select.md @@ -135,7 +135,7 @@ When the user selects a country, it will reload the regions based on the chosen ### Customize Choices.js styling -Choices.js uses a *SCSS* stylesheet to style the library. Our stylesheet extends the vendor stylesheet (of Choices.js) and adds some Tailwind-specific tweaks. Make sure your bundler handles SCSS stylesheets correctly, for example, by installing `sass`. The `splade:publish-form-stylesheets` Artisan command copies the stylesheet to the `resources` directory of your app. +Choices.js uses an *SCSS* stylesheet to style the library. Our stylesheet extends the vendor stylesheet (of Choices.js) and adds some Tailwind-specific tweaks. Make sure your bundler handles SCSS stylesheets correctly, for example, by installing `sass`. The `splade:publish-form-stylesheets` Artisan command copies the stylesheet to the `resources` directory of your app. ```bash npm install sass -D From 1b0cc8ef5fdcd30b05cebe9b8c8f3b9022d5af92 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 21:34:36 +0100 Subject: [PATCH 036/121] FilePond --- form-file.md | 2 +- form-overview.md | 2 +- introducing-splade.md | 2 +- manual-installation.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/form-file.md b/form-file.md index cea4bee..744fcd4 100644 --- a/form-file.md +++ b/form-file.md @@ -143,7 +143,7 @@ Route::post('podcast', StorePodcastController::class) ->middleware(HandleSpladeFileUploads::for('photo')); ``` -The last option is to use [Form Request](https://laravel.com/docs/9.x/validation#form-request-validation). Then, you only have to implement the `HasSpladeFileUploads` interface and use the `file` validation rule. Splade will automatically extract the keys from the rules. +The last option is to use a [Form Request](https://laravel.com/docs/9.x/validation#form-request-validation). Then, you only have to implement the `HasSpladeFileUploads` interface and use the `file` validation rule. Splade will automatically extract the keys from the rules. ```php use Illuminate\Foundation\Http\FormRequest; diff --git a/form-overview.md b/form-overview.md index a94a806..c37fe50 100644 --- a/form-overview.md +++ b/form-overview.md @@ -1,6 +1,6 @@ # Form Components -Splade comes with a set of **Form Components** to rapidly build forms. It supports model binding and validation, includes default styling, and is still fully customizable! It integrates with [Autosize](https://www.jacklmoore.com/autosize/) to automatically adjust textarea height, [Choices.js](https://github.com/Choices-js/Choices) to make selects searchable and taggable, and [Flatpickr](https://flatpickr.js.org) to provide a powerful datetime picker. +Splade comes with a set of **Form Components** to rapidly build forms. It supports model binding and validation, includes default styling, and is still fully customizable! It integrates with [Autosize](https://www.jacklmoore.com/autosize/) to automatically adjust textarea height, [Choices.js](https://github.com/Choices-js/Choices) to make selects searchable and taggable, [Flatpickr](https://flatpickr.js.org) to provide a powerful datetime picker, and [FilePond](https://pqina.nl/filepond/) for smooth file uploads. Available components: diff --git a/introducing-splade.md b/introducing-splade.md index 76723a8..80e5ae8 100644 --- a/introducing-splade.md +++ b/introducing-splade.md @@ -102,4 +102,4 @@ Here's a summary of all the cool things Splade can do: * `` component to add animations to your templates. * `Toast` component to display toasts on your page. It supports nine positions, four styles, backdrop background, and auto-dismiss. * `Table` component to automatically generate tables with support for auto-fill, searching, filtering, sorting, toggling columns, and pagination. -* `Form` components to rapidly build forms. Support for model binding, validation, Eloquent Relationships, textarea autosize, Choices.js searchable/taggable selects, and Flatpickr for date/time/range picking. \ No newline at end of file +* `Form` components to rapidly build forms. Support for model binding, validation, Eloquent Relationships, textarea autosize, Choices.js searchable/taggable selects, Flatpickr for date/time/range picking, and FilePond file uploads. \ No newline at end of file diff --git a/manual-installation.md b/manual-installation.md index 2386ed5..38c0006 100644 --- a/manual-installation.md +++ b/manual-installation.md @@ -86,7 +86,7 @@ createApp({ .mount(el); ``` -As you can see at the top, there's also a default stylesheet to support the Choices.js and Flatpickr integrations of the [Form Components](/form-overview.md). Though you probably want to import this default stylesheet into your main JavaScript file, it's completely optional. +As you can see at the top, there's also a default stylesheet to support the Choices.js, FilePond, and Flatpickr integrations of the [Form Components](/form-overview.md). Though you probably want to import this default stylesheet into your main JavaScript file, it's completely optional. In your Blade root layout, you may use the `@splade` directive inside the `body`, and the `@spladeHead` directive inside the `head`. This will render the title and meta tags, and the default `
` element where the Vue app will be mounted. From b6491f20111b407084a60bbdd895576675efbeaf Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 21:36:05 +0100 Subject: [PATCH 037/121] Update form-file.md --- form-file.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/form-file.md b/form-file.md index 744fcd4..1edec56 100644 --- a/form-file.md +++ b/form-file.md @@ -42,7 +42,7 @@ You can instantiate FilePond with a [custom set of options](https://pqina.nl/fil ```blade - + ``` ### Image Preview From 52d5c137cede9b36164b87a78e1af3ecb97f3a1c Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 21:40:36 +0100 Subject: [PATCH 038/121] Update form-file.md --- form-file.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/form-file.md b/form-file.md index 1edec56..6efca42 100644 --- a/form-file.md +++ b/form-file.md @@ -113,11 +113,11 @@ There are three ways of handling the temporary upload. First, you may use the `H ```php use Illuminate\Http\Request; -use ProtoneMedia\Splade\FileUploads\HandleSpladeFileUploads; +use ProtoneMedia\Splade\FileUploads\HandleSpladeFileUploads; // [tl! add] public function store(Request $request) { - HandleSpladeFileUploads::forRequest($request); + HandleSpladeFileUploads::forRequest($request); // [tl! add] $request->validate([ 'photo' => ['required', 'file', 'image'], @@ -137,19 +137,19 @@ The second option is to use a Route Middleware. You may use the same `HandleSpla ```php Route::post('podcast', StorePodcastController::class) - ->middleware(HandleSpladeFileUploads::class); + ->middleware(HandleSpladeFileUploads::class); // [tl! add] Route::post('podcast', StorePodcastController::class) - ->middleware(HandleSpladeFileUploads::for('photo')); + ->middleware(HandleSpladeFileUploads::for('photo')); // [tl! add] ``` The last option is to use a [Form Request](https://laravel.com/docs/9.x/validation#form-request-validation). Then, you only have to implement the `HasSpladeFileUploads` interface and use the `file` validation rule. Splade will automatically extract the keys from the rules. ```php use Illuminate\Foundation\Http\FormRequest; -use ProtoneMedia\Splade\FileUploads\HasSpladeFileUploads; +use ProtoneMedia\Splade\FileUploads\HasSpladeFileUploads; // [tl! add] -class StorePodcastRequest extends FormRequest implements HasSpladeFileUploads +class StorePodcastRequest extends FormRequest implements HasSpladeFileUploads [tl! add] { public function rules() { From 6e0907369c1352deeaba6806f519a9471972e13f Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 21:41:10 +0100 Subject: [PATCH 039/121] Update form-file.md --- form-file.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/form-file.md b/form-file.md index 6efca42..588a488 100644 --- a/form-file.md +++ b/form-file.md @@ -149,7 +149,7 @@ The last option is to use a [Form Request](https://laravel.com/docs/9.x/validati use Illuminate\Foundation\Http\FormRequest; use ProtoneMedia\Splade\FileUploads\HasSpladeFileUploads; // [tl! add] -class StorePodcastRequest extends FormRequest implements HasSpladeFileUploads [tl! add] +class StorePodcastRequest extends FormRequest implements HasSpladeFileUploads // [tl! add] { public function rules() { From 0a6a045f88b844840d713be34b77e093bc6c5fc6 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 23:45:52 +0100 Subject: [PATCH 040/121] Update form-file.md --- form-file.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/form-file.md b/form-file.md index 588a488..ccac09f 100644 --- a/form-file.md +++ b/form-file.md @@ -160,10 +160,6 @@ class StorePodcastRequest extends FormRequest implements HasSpladeFileUploads } ``` -### Custom temporary directory - -By default, Splade uses the `/storage/splade-temporary-file-uploads` directory for temporary uploads. If you want to use a custom [Filesystem disk](https://laravel.com/docs/9.x/filesystem#configuration), you may update the `file_uploads.disk` key in the `splade.php` [configuration file](/customization.md). For now, it only supports local disks. - ### Cleanup temporary uploads It may happen that temporarily uploaded files are not being used and will fill the temporary directory. Splade comes with a built-in Artisan command to delete all files that are older than one hour: @@ -174,6 +170,10 @@ php artisan splade:cleanup-uploads You may change the lifetime of temporary files with the `file_uploads.temporary_file_lifetime` key in the `splade.php` [configuration file](/customization.md). +### Custom temporary directory + +By default, Splade uses the `/storage/splade-temporary-file-uploads` directory for temporary uploads. If you want to use a custom [Filesystem disk](https://laravel.com/docs/9.x/filesystem#configuration), you may update the `file_uploads.disk` key in the `splade.php` [configuration file](/customization.md). For now, it only supports local disks. + ### Customize FilePond styling FilePond uses an *SCSS* stylesheet to style the library. Our stylesheet extends the vendor stylesheet (of FilePond) and adds some Tailwind-specific tweaks. Make sure your bundler handles SCSS stylesheets correctly, for example, by installing `sass`. The `splade:publish-form-stylesheets` Artisan command copies the stylesheet to the `resources` directory of your app. From ce070b38aef1dec8b5bb6ea0019319f5a0733188 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 23:47:19 +0100 Subject: [PATCH 041/121] Update form-file.md --- form-file.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/form-file.md b/form-file.md index ccac09f..a715961 100644 --- a/form-file.md +++ b/form-file.md @@ -109,7 +109,7 @@ Next, in the template, add the `server` attribute to the component. From now on, Splade will store the file in a temporary directory and report the path to the file back to the File component. So when the user submits the form, it will send this path instead of uploading the file. -There are three ways of handling the temporary upload. First, you may use the `HandleSpladeFileUploads` class, for example, in your controller: +There are three ways of handling the temporary upload. You may choose the option that best fits your needs. First, you may use the `HandleSpladeFileUploads` class, for example, in your controller: ```php use Illuminate\Http\Request; From 25fb9d6f7061405221e303b5655e47d4052b1639 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Wed, 16 Nov 2022 23:47:55 +0100 Subject: [PATCH 042/121] Update form-file.md --- form-file.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/form-file.md b/form-file.md index a715961..fe72df4 100644 --- a/form-file.md +++ b/form-file.md @@ -162,7 +162,7 @@ class StorePodcastRequest extends FormRequest implements HasSpladeFileUploads ### Cleanup temporary uploads -It may happen that temporarily uploaded files are not being used and will fill the temporary directory. Splade comes with a built-in Artisan command to delete all files that are older than one hour: +It may happen that temporarily uploaded files are not being used and will fill the temporary directory. Splade comes with a built-in Artisan command to delete all unused files that are older than one hour: ```bash php artisan splade:cleanup-uploads From ec61c6c10615b1f457bfc12c56e9597328aa0156 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Sat, 19 Nov 2022 13:03:01 +0100 Subject: [PATCH 043/121] Update upgrading.md --- upgrading.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/upgrading.md b/upgrading.md index fab4ace..e988c11 100644 --- a/upgrading.md +++ b/upgrading.md @@ -14,4 +14,12 @@ Make sure to clear Laravel's [view cache](https://laravel.com/docs/9.x/views#opt php artisan view:clear ``` -Lastly, if you've published the config file or the Blade templates, make sure your customizations are up-to-date with the defaults. \ No newline at end of file +Lastly, if you've published the config file or the Blade templates, make sure your customizations are up-to-date with the defaults. + +## Verify installed packages + +You may use the built-in Artisan Command to show the installed versions of the packages: + +```bash +php artisan splade:show-versions +``` \ No newline at end of file From 8d2e0b3d17ee7e15fd4a4cee1828a565bd68ebb4 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Sat, 19 Nov 2022 14:28:55 +0100 Subject: [PATCH 044/121] Update manual-installation.md --- manual-installation.md | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/manual-installation.md b/manual-installation.md index 38c0006..7527a5e 100644 --- a/manual-installation.md +++ b/manual-installation.md @@ -69,12 +69,12 @@ module.exports = { }; ``` -In the `createApp` section of your main JavaScript file, you need to use the Splade plugin, as well as the custom render method: +In the `createApp` section of your main JavaScript file, you need to use the Splade plugin, as well as the custom render method. Note how it imports the `createApp` method from the *bundler* Vue build, as that build includes the [Vue template compiler](https://vuejs.org/guide/scaling-up/tooling.html#note-on-in-browser-template-compilation). ```js import "@protonemedia/laravel-splade/dist/style.css"; -import { createApp } from 'vue' +import { createApp } from "vue/dist/vue.esm-bundler.js"; import { renderSpladeApp, SpladePlugin } from '@protonemedia/laravel-splade' const el = document.getElementById('app') @@ -104,20 +104,4 @@ Splade assumes the path of this file is `resources/views/root.blade.php`. If you ```php Splade::setRootView('base-layout'); -``` - -Lastly, in the `vite.config.js` file, you need to add an alias for the [Vue template compiler](https://vuejs.org/guide/scaling-up/tooling.html#note-on-in-browser-template-compilation): - -```js -export default defineConfig({ - ... - - resolve: { - alias: { - vue: 'vue/dist/vue.esm-bundler' - } - }, - - ... -}); -``` +``` \ No newline at end of file From 43988a2d88b0c012f7e0dca536d93db696de6bde Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Sat, 19 Nov 2022 14:57:27 +0100 Subject: [PATCH 045/121] Update x-link.md --- x-link.md | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/x-link.md b/x-link.md index e5da6fe..0d3fc9e 100644 --- a/x-link.md +++ b/x-link.md @@ -45,4 +45,34 @@ createApp({ render: renderSpladeApp({ el }) }) 'transform_anchors': true, }) .mount(el); -``` \ No newline at end of file +``` + +## Method, Headers, and Request Data + +By default, the asynchronous page load is a `GET` request, but you may change this with the `method` attribute: + +```blade +Start new template +``` + +The component also supports custom headers and request data. While you can use the `headers` and `data` attributes on the `Link` component, there's also a Blade variant of the component. Just like the [Data component](/x-data.md), it allows you to pass a PHP value *or* a JavaScript object: + +The value passed to the `data` attribute will be parsed by Vue, not by PHP. + +```blade + +``` + +If you want to parse the value by PHP, you may use the `:data` attribute (note the colon). + +```blade + +``` + +You can do the same for adding headers: + +```blade + + + +``` From 967b7c48e64e0d1e654441a322ba9c091bb367aa Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Sat, 19 Nov 2022 15:08:53 +0100 Subject: [PATCH 046/121] Update form-select.md --- form-select.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/form-select.md b/form-select.md index d1c7026..0d082c4 100644 --- a/form-select.md +++ b/form-select.md @@ -147,4 +147,22 @@ Then import the stylesheet in your main JavaScript file (instead of the default ```js import "../css/choices.scss" -``` \ No newline at end of file +``` + +### Laravel Dusk macro + +Splade has two macros that help you test Choices.js instances with [Laravel Dusk](https://laravel.com/docs/9.x/dusk). Instead of calling `select` with the *field* and *value* arguments, you may use the `choicesSelect` method: + +```php +$browser->select('size', 'Large'); // [tl! remove] + +$browser->choicesSelect('size', 'Large'); // [tl! add] +``` + +If you want to remove an item from a Choices.js instance with multiple options, you may use the `choicesRemoveItem` method: + +```php +$browser->choicesRemoveItem('countries[]', 'NL'); +``` + +You may change the name of the macros with the `dusk.choices_select_macro` and `dusk.choices_remove_item_macro` keys in the `splade.php` [configuration file](/customization.md). \ No newline at end of file From 713b86cb886c5177ffa8ddd6fb4563c8212ce1bb Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Sun, 20 Nov 2022 13:18:09 +0100 Subject: [PATCH 047/121] Update x-form.md --- x-form.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/x-form.md b/x-form.md index 8afef70..57fc718 100644 --- a/x-form.md +++ b/x-form.md @@ -66,6 +66,26 @@ Instead of fully unguarding the form, you may specify which attributes to unguar You can read more about this behaviour on the [Form Model Binding](/form-model-binding-attributes.md) page. Even better, the dedicated [Form Components](/form-overview.md) handle this automatically for you. +## Using Data + +Besides binding form data to an input element, you may the form data the build interactive elements just like the [Data component](/x-data.md). For example, you could use the `form` object to toggle classes or show an element. + +```blade + + {{-- Interact with the value of the data --}} + +

Your name is:

+ + {{-- Toggle classes based on the value of the data --}} + + + + {{-- Show elements based on the value of the data --}} + + +
+``` + ## Confirmation You may use the `confirm` attribute to show a confirmation dialog before the form is submitted: From f5ed37db12f269b96bb974bfc486c0ac23d43122 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Mon, 21 Nov 2022 10:25:38 +0100 Subject: [PATCH 048/121] Update x-form.md --- x-form.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/x-form.md b/x-form.md index 57fc718..7e4be3e 100644 --- a/x-form.md +++ b/x-form.md @@ -193,6 +193,40 @@ There are several props that you can use to show the state of the form: ``` +## Form API + +The `form` object has several additional methods and properties that you could use. With the `$put` method, you can set a value: + +```vue + +``` + +The `$all` property could help you debug the Form by printing all values: + +```vue +
+```
+
+If you'd somehow need to submit the Form with a custom trigger, you can use the `submit` method:
+
+```vue
+
Start
+``` + +As shown above, there's an `errors` object to evaluate validation errors, but there's also a `hasError` method to determine whether there is an error: + +```vue +... +``` + +If you want full access to the server-side error bag, you may use the `rawErrors` object. + +```vue +
+ ... +
+``` + ## Form components While writing traditional input elements is fine, Splade comes with various components to build forms even faster. Make sure to check out the [documentation page](/form-overview.md)! \ No newline at end of file From 551b08c71ac3ada0b00b0e523c16f77448f6208e Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Mon, 21 Nov 2022 10:26:11 +0100 Subject: [PATCH 049/121] Update x-form.md --- x-form.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-form.md b/x-form.md index 7e4be3e..b3dea21 100644 --- a/x-form.md +++ b/x-form.md @@ -197,31 +197,31 @@ There are several props that you can use to show the state of the form: The `form` object has several additional methods and properties that you could use. With the `$put` method, you can set a value: -```vue +```blade ``` The `$all` property could help you debug the Form by printing all values: -```vue +```blade
 ```
 
 If you'd somehow need to submit the Form with a custom trigger, you can use the `submit` method:
 
-```vue
+```blade
 
Start
``` As shown above, there's an `errors` object to evaluate validation errors, but there's also a `hasError` method to determine whether there is an error: -```vue +```blade ... ``` If you want full access to the server-side error bag, you may use the `rawErrors` object. -```vue +```blade
...
From e1cedd41ccb11f08aa29a5b840a1a34e6e08bc9a Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Mon, 21 Nov 2022 10:49:10 +0100 Subject: [PATCH 050/121] Create custom-form-components.md --- custom-form-components.md | 280 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 custom-form-components.md diff --git a/custom-form-components.md b/custom-form-components.md new file mode 100644 index 0000000..4da8ed1 --- /dev/null +++ b/custom-form-components.md @@ -0,0 +1,280 @@ +# Custom Form components + +Splade comes with a great set of [built-in Form Components](/form-overview.md), but your application might require a custom component as part of a form. There are several ways to implement this, so we’ll look at implementing the same custom component differently. + +## Card Select component + +The component we'll be implementing is a *card selector*. In this example, two cards represent a subscription plan (*basic* or *pro*). Clicking on one of the cards will update the form data, as the cards are built around a `radio` input element. Here's what it looks like: + +## Blade implementation + +First, let's take a look at a Blade implementation. This implementation works without any custom Vue components. For the sake of simplicity, we'll hard-code both plans, and we don't extract each card into a separate component. + +```blade + +
+ + {{-- Plan Basic --}} + + + {{-- Plan Pro --}} + + +
+
+``` + +Let's break down what's happening here. First, there's a [Form component](/x-form.md) with a default *basic* plan. + +```blade + +``` + +Then there are two Cards built around a `label` element. The border color is based on whether the plan is selected or not. + +```blade +