rblade 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,12 +1,41 @@
1
1
  # RBlade Templates
2
2
 
3
- - [Introduction](#introduction)
4
- - [Supercharging Blade With Livewire](#supercharging-blade-with-livewire)
5
- - [Displaying Data](#displaying-data)
6
- - [HTML Entity Encoding](#html-entity-encoding)
7
- - [Blade and JavaScript Frameworks](#blade-and-javascript-frameworks)
8
-
9
- **TODO redo TOC**
3
+ - [RBlade Templates](#rblade-templates)
4
+ * [Introduction](#introduction)
5
+ * [Displaying Data](#displaying-data)
6
+ + [HTML Entity Encoding](#html-entity-encoding)
7
+ + [Blade and JavaScript Frameworks](#blade-and-javascript-frameworks)
8
+ - [The `@verbatim` Directive](#the-at-verbatim-directive)
9
+ * [RBlade Directives](#rblade-directives)
10
+ + [If Statements](#if-statements)
11
+ - [Environment Directives](#environment-directives)
12
+ + [Case Statements](#case-statements)
13
+ + [Loops](#loops)
14
+ + [Conditional Classes & Styles](#conditional-classes-and-styles)
15
+ + [Additional Attributes](#additional-attributes)
16
+ + [The `@once` Directive](#the-once-directive)
17
+ + [Raw Ruby](#raw-ruby)
18
+ + [Comments](#comments)
19
+ * [Components](#components)
20
+ + [Rendering Components](#rendering-components)
21
+ - [Namespaces](#namespaces)
22
+ + [Passing Data to Components](#passing-data-to-components)
23
+ - [Component Properties](#component-properties)
24
+ - [Short Attribute Syntax](#short-attribute-syntax)
25
+ - [Escaping Attribute Rendering](#escaping-attribute-rendering)
26
+ + [Component Attributes](#component-attributes)
27
+ - [Default & Merged Attributes](#default-and-merged-attributes)
28
+ - [Non-Class Attribute Merging](#non-class-attribute-merging)
29
+ - [Conditionally Merge Classes](#conditionally-merge-classes)
30
+ - [Retrieving and Filtering Attributes](#retrieving-and-filtering-attributes)
31
+ + [Slots](#slots)
32
+ - [Slot Attributes](#slot-attributes)
33
+ + [Registering Additional Component Directories](#registering-additional-component-directories)
34
+ + [Index Components](#index-components)
35
+ * [Forms](#forms)
36
+ + [Old Input](#old-input)
37
+ + [Method Field](#method-field)
38
+ * [Stacks](#stacks)
10
39
 
11
40
  <a name="introduction"></a>
12
41
  ## Introduction
@@ -98,57 +127,28 @@ In addition to template inheritance and displaying data, RBlade also provides co
98
127
  <a name="if-statements"></a>
99
128
  ### If Statements
100
129
 
101
- You may construct `if` statements using the `@if`, `@elseif`, `@else`, `@endif`, `@unless`, and `@endunless` directives. These directives function identically to their Ruby counterparts:
130
+ You may construct `if` statements using the `@if`, `@elseIf`, `@else`, `@endIf`, `@unless`, and `@endUnless` directives. These directives function identically to their Ruby counterparts:
102
131
 
103
132
  ```rblade
104
133
  @unless(records.nil?)
105
134
  @if (records.count === 1)
106
135
  I have one record!
107
- @elseif (records.count > 1)
136
+ @elseIf (records.count > 1)
108
137
  I have multiple records!
109
138
  @else
110
139
  I don't have any records!
111
- @endif
112
- @endunless
140
+ @endIf
141
+ @endUnless
113
142
  ```
114
143
 
115
- In addition to the conditional directives already discussed, the `@isset` and `@empty` directives may be used as convenient shortcuts for their respective PHP functions:
116
- **TODO add nil? directive?**
117
- ```rblade
118
- @isset($records)
119
- // $records is defined and is not null...
120
- @endisset
121
-
122
- @empty($records)
123
- // $records is "empty"...
124
- @endempty
125
- ```
126
-
127
- <a name="authentication-directives"></a>
128
- #### Authentication Directives
129
- **TODO add authentication directives?**
130
- The `@auth` and `@guest` directives may be used to quickly determine if the current user is [authenticated](/docs/{{version}}/authentication) or is a guest:
131
-
132
- ```rblade
133
- @auth
134
- // The user is authenticated...
135
- @endauth
136
-
137
- @guest
138
- // The user is not authenticated...
139
- @endguest
140
- ```
141
-
142
- If needed, you may specify the authentication guard that should be checked when using the `@auth` and `@guest` directives:
144
+ In addition to the conditional directives above, the `@blank?`, `defined?`, `@empty?`, `@nil?` and `@present` directives may be used as convenient shortcuts:
143
145
 
144
146
  ```rblade
145
- @auth('admin')
146
- // The user is authenticated...
147
- @endauth
148
-
149
- @guest('admin')
150
- // The user is not authenticated...
151
- @endguest
147
+ @present?(records)
148
+ // records is defined and is not nil
149
+ @else
150
+ // These directives are shortcuts to if statements so @else may be used
151
+ @endempty?
152
152
  ```
153
153
 
154
154
  <a name="environment-directives"></a>
@@ -159,7 +159,7 @@ You may check if the application is running in the production environment using
159
159
  ```rblade
160
160
  @production
161
161
  // Production specific content...
162
- @endproduction
162
+ @endProduction
163
163
  ```
164
164
 
165
165
  Or, you may determine if the application is running in a specific environment using the `@env` directive:
@@ -167,30 +167,17 @@ Or, you may determine if the application is running in a specific environment us
167
167
  ```rblade
168
168
  @env('staging')
169
169
  // The application is running in "staging"...
170
- @endenv
170
+ @endEnv
171
171
 
172
172
  @env(['staging', 'production'])
173
173
  // The application is running in "staging" or "production"...
174
- @endenv
175
- ```
176
-
177
- <a name="session-directives"></a>
178
- #### Session Directives
179
- **TODO add sessuib directives**
180
- The `@session` directive may be used to determine if a [session](/docs/{{version}}/session) value exists. If the session value exists, the template contents within the `@session` and `@endsession` directives will be evaluated. Within the `@session` directive's contents, you may echo the `$value` variable to display the session value:
181
-
182
- ```rblade
183
- @session('status')
184
- <div class="p-4 bg-green-100">
185
- {{ $value }}
186
- </div>
187
- @endsession
174
+ @endEnv
188
175
  ```
189
176
 
190
177
  <a name="switch-statements"></a>
191
178
  ### Case Statements
192
179
 
193
- Case statements can be constructed using the `@case`, `@when`, `@else` and `@endcase` directives:
180
+ Case statements can be constructed using the `@case`, `@when`, `@else` and `@endCase` directives:
194
181
 
195
182
  ```rblade
196
183
  @case(i)
@@ -200,7 +187,7 @@ Case statements can be constructed using the `@case`, `@when`, `@else` and `@end
200
187
  Second case...
201
188
  @else
202
189
  Default case...
203
- @endcase
190
+ @endCase
204
191
  ```
205
192
 
206
193
  <a name="loops"></a>
@@ -211,28 +198,28 @@ In addition to conditional statements, RBlade provides simple directives for wor
211
198
  ```rblade
212
199
  @for (i in 0...10)
213
200
  The current value is {{ i }}
214
- @endfor
201
+ @endFor
215
202
 
216
203
  {{-- Compiles to users.each do |user| ... --}}
217
204
  @each (user in users)
218
205
  <p>This is user {{ user.id }}</p>
219
- @endeach
206
+ @endEach
220
207
 
221
- @forelse (name in [])
208
+ @forElse (name in [])
222
209
  <li>{{ name }}</li>
223
210
  @empty
224
211
  <p>No names</p>
225
- @endforelse
212
+ @endForElse
226
213
 
227
- @eachelse (user in users)
214
+ @eachElse (user in users)
228
215
  <li>{{ user.name }}</li>
229
216
  @empty
230
217
  <p>No users</p>
231
- @endeachelse
218
+ @endEachElse
232
219
 
233
220
  @while (true)
234
221
  <p>I'm looping forever.</p>
235
- @endwhile
222
+ @endWhile
236
223
  ```
237
224
 
238
225
  When using loops you can also skip the current iteration or end the loop using the `@next` and `@break` directives:
@@ -241,79 +228,29 @@ When using loops you can also skip the current iteration or end the loop using t
241
228
  for (user in users)
242
229
  @if (user.type == 1)
243
230
  @next
244
- @endif
231
+ @endIf
245
232
 
246
233
  <li>{{ user.name }}</li>
247
234
 
248
235
  @if (user.number == 5)
249
236
  @break
250
- @endif
251
- @endfor
237
+ @endIf
238
+ @endFor
252
239
  ```
253
240
 
254
241
  You may also include the continuation or break condition within the directive declaration:
255
242
 
256
243
  ```rblade
257
- @foreach (user in users)
244
+ @for (user in users)
258
245
  @next(user.type == 1)
259
246
 
260
- <li>{{ $user->name }}</li>
247
+ <li>{{ user.name }}</li>
261
248
 
262
249
  @break(user.number == 5)
263
- @endforeach
250
+ @endFor
264
251
  ```
265
252
 
266
- <a name="the-loop-variable"></a>
267
- ### The Loop Variable
268
- **TODO can/should we add this?**
269
- While iterating through a `foreach` loop, a `$loop` variable will be available inside of your loop. This variable provides access to some useful bits of information such as the current loop index and whether this is the first or last iteration through the loop:
270
-
271
- ```rblade
272
- @foreach ($users as $user)
273
- @if ($loop->first)
274
- This is the first iteration.
275
- @endif
276
-
277
- @if ($loop->last)
278
- This is the last iteration.
279
- @endif
280
-
281
- <p>This is user {{ $user->id }}</p>
282
- @endforeach
283
- ```
284
-
285
- If you are in a nested loop, you may access the parent loop's `$loop` variable via the `parent` property:
286
-
287
- ```rblade
288
- @foreach ($users as $user)
289
- @foreach ($user->posts as $post)
290
- @if ($loop->parent->first)
291
- This is the first iteration of the parent loop.
292
- @endif
293
- @endforeach
294
- @endforeach
295
- ```
296
-
297
- The `$loop` variable also contains a variety of other useful properties:
298
-
299
- <div class="overflow-auto">
300
-
301
- | Property | Description |
302
- | ------------------ | ------------------------------------------------------ |
303
- | `$loop->index` | The index of the current loop iteration (starts at 0). |
304
- | `$loop->iteration` | The current loop iteration (starts at 1). |
305
- | `$loop->remaining` | The iterations remaining in the loop. |
306
- | `$loop->count` | The total number of items in the array being iterated. |
307
- | `$loop->first` | Whether this is the first iteration through the loop. |
308
- | `$loop->last` | Whether this is the last iteration through the loop. |
309
- | `$loop->even` | Whether this is an even iteration through the loop. |
310
- | `$loop->odd` | Whether this is an odd iteration through the loop. |
311
- | `$loop->depth` | The nesting level of the current loop. |
312
- | `$loop->parent` | When in a nested loop, the parent's loop variable. |
313
-
314
- </div>
315
-
316
- <a name="conditional-classes"></a>
253
+ <a name="conditional-classes-and-styles"></a>
317
254
  ### Conditional Classes & Styles
318
255
 
319
256
  The `@class` directive conditionally adds CSS classes. The directive accepts a `Hash` of classes where the key contains the class or classes you wish to add, and the value is a boolean expression:
@@ -322,7 +259,7 @@ The `@class` directive conditionally adds CSS classes. The directive accepts a `
322
259
  @ruby
323
260
  isActive = false;
324
261
  hasError = true;
325
- @endruby
262
+ @endRuby
326
263
 
327
264
  <span @class({
328
265
  "p-4": true,
@@ -339,7 +276,7 @@ Likewise, the `@style` directive may be used to conditionally add inline CSS sty
339
276
  ```rblade
340
277
  @ruby
341
278
  isActive = true;
342
- @endruby
279
+ @endRuby
343
280
 
344
281
  <span @style({
345
282
  "background-color: red": true,
@@ -369,7 +306,7 @@ Likewise, the `@selected` directive may be used to indicate if a given select op
369
306
  <option value="{{ version }}" @selected(version == selectedVersion)>
370
307
  {{ version }}
371
308
  </option>
372
- @endeach
309
+ @endEach
373
310
  </select>
374
311
  ```
375
312
 
@@ -446,20 +383,7 @@ In some situations, it's useful to embed Ruby code into your views. You can use
446
383
  ```rblade
447
384
  @ruby
448
385
  counter = 1;
449
- @endruby
450
- ```
451
-
452
- **TODO add require?**
453
- Or, if you only need to use PHP to import a class, you may use the `@use` directive:
454
-
455
- ```rblade
456
- @use('App\Models\Flight')
457
- ```
458
-
459
- A second argument may be provided to the `@use` directive to alias the imported class:
460
-
461
- ```php
462
- @use('App\Models\Flight', 'FlightModel')
386
+ @endRuby
463
387
  ```
464
388
 
465
389
  <a name="comments"></a>
@@ -568,7 +492,7 @@ When passing attributes to components, you may also use a "short attribute" synt
568
492
  <a name="escaping-attribute-rendering"></a>
569
493
  #### Escaping Attribute Rendering
570
494
 
571
- Since some JavaScript frameworks such as Alpine.js also use colon-prefixed attributes, you may use a double colon (`::`) prefix to inform RBlade that the attribute is not a PHP expression. For example, given the following component:
495
+ Since some JavaScript frameworks such as Alpine.js also use colon-prefixed attributes, you may use a double colon (`::`) prefix to inform RBlade that the attribute is not a Ruby expression. For example, given the following component:
572
496
 
573
497
  ```rblade
574
498
  <x-button ::class="{ danger: isDeleting }">
@@ -593,8 +517,6 @@ We've already examined how to pass data attributes to a component; however, some
593
517
  <x-alert type="error" :message class="mt-4"/>
594
518
  ```
595
519
 
596
- **TODO remove from attributes bag using @props? Rename to attributes bag?**
597
-
598
520
  All of the attributes that are not part of the component's constructor will automatically be added to the component's "attribute manager". This attribute manager is automatically made available to the component via the `attributes` variable. All of the attributes may be rendered within the component by printing this variable:
599
521
 
600
522
  ```rblade
@@ -603,8 +525,8 @@ All of the attributes that are not part of the component's constructor will auto
603
525
  </div>
604
526
  ```
605
527
 
606
- <a name="default-merged-attributes"></a>
607
- #### Default / Merged Attributes
528
+ <a name="default-and-merged-attributes"></a>
529
+ #### Default & Merged Attributes
608
530
 
609
531
  Sometimes you may need to specify default values for attributes or merge additional values into some of the component's attributes. To accomplish this, you may use the attribute manager's `merge` method. This method is particularly useful for defining a set of default CSS classes that should always be applied to a component:
610
532
 
@@ -657,31 +579,22 @@ The rendered HTML of the `button` component in this example would be:
657
579
  </button>
658
580
  ```
659
581
 
660
- **Todo add prepends**
661
- If you would like an attribute other than `class` or `style` to have its default value and injected values joined together, you can use the `prepends` method. In this example, the `data-controller` attribute will always begin with `profile-controller` and any additional injected `data-controller` values will be placed after this default value:
662
-
663
- ```rblade
664
- <div {{ attributes.merge({"data-controller": attributes.prepends("profile-controller")}) }}>
665
- {{ slot }}
666
- </div>
667
- ```
668
-
669
582
  <a name="conditionally-merge-classes"></a>
670
583
  #### Conditionally Merge Classes
671
- **TODO this**
672
- Sometimes you may wish to merge classes if a given condition is `true`. You can accomplish this via the `class` method, which accepts an array of classes where the array key contains the class or classes you wish to add, while the value is a boolean expression. If the array element has a numeric key, it will always be included in the rendered class list:
584
+
585
+ Sometimes you may wish to merge classes if a given condition is `true`. You can accomplish this via the `class` method, which accepts a Hash of classes where the array key contains the class or classes you wish to add, while the value is a boolean expression:
673
586
 
674
587
  ```rblade
675
- <div {{ $attributes->class(['p-4', 'bg-red' => $hasError]) }}>
676
- {{ $message }}
588
+ <div {{ attributes.class({'p-4': true, 'bg-red': hasError}) }}>
589
+ {{ message }}
677
590
  </div>
678
591
  ```
679
592
 
680
593
  If you need to merge other attributes onto your component, you can chain the `merge` method onto the `class` method:
681
594
 
682
595
  ```rblade
683
- <button {{ $attributes->class(['p-4'])->merge(['type' => 'button']) }}>
684
- {{ $slot }}
596
+ <button {{ attributes.class({'bg-red': hasError}).merge({type: 'button'}) }}>
597
+ {{ slot }}
685
598
  </button>
686
599
  ```
687
600
 
@@ -691,62 +604,39 @@ If you need to merge other attributes onto your component, you can chain the `me
691
604
  <a name="filtering-attributes"></a>
692
605
  #### Retrieving and Filtering Attributes
693
606
 
694
- **Todo this**
695
-
696
- You may filter attributes using the `filter` method. This method accepts a closure which should return `true` if you wish to retain the attribute in the attribute bag:
697
-
698
- ```rblade
699
- {{ $attributes->filter(fn (string $value, string $key) => $key == 'foo') }}
700
- ```
607
+ The attributes manager is a wrapper around the Ruby Hash class. Unless explicitly overwritten, any methods called on the attributes manager will call that same method on the underlying Hash.
701
608
 
702
- For convenience, you may use the `whereStartsWith` method to retrieve all attributes whose keys begin with a given string:
609
+ You may filter attributes using the `filter` and `slice` methods. These methods call `filter` and `slice` on the underlying Hash and return a new attributes manager with the result.
703
610
 
704
611
  ```rblade
705
- {{ $attributes->whereStartsWith('wire:model') }}
612
+ {{ attributes.filter { |k, v| k == 'foo'} }}
613
+ {{ attributes.slice :foo }}
706
614
  ```
707
615
 
708
- Conversely, the `whereDoesntStartWith` method may be used to exclude all attributes whose keys begin with a given string:
616
+ If you would like to check if an attribute is present on the component, you may use the `has?` method. This method accepts the attribute name as its only argument and returns a boolean indicating whether or not the attribute is present:
709
617
 
710
618
  ```rblade
711
- {{ $attributes->whereDoesntStartWith('wire:model') }}
712
- ```
713
-
714
- Using the `first` method, you may render the first attribute in a given attribute bag:
715
-
716
- ```rblade
717
- {{ $attributes->whereStartsWith('wire:model')->first() }}
718
- ```
719
-
720
- If you would like to check if an attribute is present on the component, you may use the `has` method. This method accepts the attribute name as its only argument and returns a boolean indicating whether or not the attribute is present:
721
-
722
- ```rblade
723
- @if ($attributes->has('class'))
619
+ @if (attributes.has?(:class))
724
620
  <div>Class attribute is present</div>
725
621
  @endif
726
622
  ```
727
623
 
728
- If an array is passed to the `has` method, the method will determine if all of the given attributes are present on the component:
624
+ If multiple parameters are passed to the `has?` method, the method will determine if all of the given attributes are present on the component:
729
625
 
730
626
  ```rblade
731
- @if ($attributes->has(['name', 'class']))
627
+ @if (attributes.has?('name', 'class'))
732
628
  <div>All of the attributes are present</div>
733
629
  @endif
734
630
  ```
735
631
 
736
- The `hasAny` method may be used to determine if any of the given attributes are present on the component:
632
+ The `has_any?` method may be used to determine if any of the given attributes are present on the component:
737
633
 
738
634
  ```rblade
739
- @if ($attributes->hasAny(['href', ':href', 'v-bind:href']))
635
+ @if (attributes.has_any?('href', ':href', 'v-bind:href'))
740
636
  <div>One of the attributes is present</div>
741
637
  @endif
742
638
  ```
743
639
 
744
- You may retrieve a specific attribute's value using the `get` method:
745
-
746
- ```rblade
747
- {{ $attributes->get('class') }}
748
- ```
749
-
750
640
  <a name="slots"></a>
751
641
  ### Slots
752
642
 
@@ -789,14 +679,14 @@ You may define the content of the named slot using the `x-slot` tag. Any content
789
679
  <strong>Whoops!</strong> Something went wrong!
790
680
  </x-alert>
791
681
  ```
792
- **TODO this**
793
- You may invoke a slot's `isEmpty` method to determine if the slot contains content:
682
+
683
+ The slot object extends the String interface, so you can invoke a slot's `empty?` method to determine if the slot contains content:
794
684
 
795
685
  ```rblade
796
686
  <span class="alert-title">{{ title }}</span>
797
687
 
798
688
  <div class="alert alert-danger">
799
- @if (slot.isEmpty)
689
+ @if (slot.empty?)
800
690
  This is default content if the slot is empty.
801
691
  @else
802
692
  {{ slot }}
@@ -804,29 +694,6 @@ You may invoke a slot's `isEmpty` method to determine if the slot contains conte
804
694
  </div>
805
695
  ```
806
696
 
807
- Additionally, the `hasActualContent` method may be used to determine if the slot contains any "actual" content that is not an HTML comment:
808
-
809
- ```rblade
810
- @if (slot.hasActualContent)
811
- The scope has non-comment content.
812
- @endif
813
- ```
814
-
815
- <a name="scoped-slots"></a>
816
- #### Scoped Slots
817
- **TODO can we do this easily?**
818
- If you have used a JavaScript framework such as Vue, you may be familiar with "scoped slots", which allow you to access data or methods from the component within your slot. You may achieve similar behavior in Laravel by defining public methods or properties on your component and accessing the component within your slot via the `$component` variable. In this example, we will assume that the `x-alert` component has a public `formatAlert` method defined on its component class:
819
-
820
- ```rblade
821
- <x-alert>
822
- <x-slot:title>
823
- {{ $component->formatAlert('Server Error') }}
824
- </x-slot>
825
-
826
- <strong>Whoops!</strong> Something went wrong!
827
- </x-alert>
828
- ```
829
-
830
697
  <a name="slot-attributes"></a>
831
698
  #### Slot Attributes
832
699
 
@@ -848,15 +715,14 @@ Like RBlade components, you may assign additional [attributes](#component-attrib
848
715
 
849
716
  To interact with slot attributes, you may access the `attributes` property of the slot's variable. For more information on how to interact with attributes, please consult the documentation on [component attributes](#component-attributes):
850
717
 
851
- **TODO allow class to contain a string**
852
718
  ```rblade
853
719
  @props({
854
720
  "heading": _required,
855
721
  "footer": _required,
856
722
  })
857
723
 
858
- <div {{ attributes.class(['border']) }}>
859
- <h1 {{ heading.attributes->class('text-lg': true) }}>
724
+ <div {{ attributes.class('border') }}>
725
+ <h1 {{ heading.attributes.class('text-lg') }}>
860
726
  {{ heading }}
861
727
  </h1>
862
728
 
@@ -868,16 +734,6 @@ To interact with slot attributes, you may access the `attributes` property of th
868
734
  </div>
869
735
  ```
870
736
 
871
- <a name="dynamic-components"></a>
872
- ### Dynamic Components
873
- **TODO add this**
874
- Sometimes you may need to render a component without knowing which component should be rendered until runtime. In this situation, you may use RBlade's built-in `dynamic-component` component to render the component based on a runtime value or variable:
875
-
876
- ```rblade
877
- @ruby(componentName = "secondary-button")
878
- <x-dynamic-component :component="componentName" class="mt-4" />
879
- ```
880
-
881
737
  <a name="registering-additional-component-directories"></a>
882
738
  ### Registering Additional Component Directories
883
739
 
@@ -895,33 +751,6 @@ RBlade::ComponentStore.add_path(Rails.root.join("app", "views", "partials"), "pa
895
751
 
896
752
  If multiple directories are registered with the same namespace, RBlade will search for components in all the directories in the order they were registered.
897
753
 
898
- <a name="manually-registering-components"></a>
899
- ### Manually Registering Components
900
- **TODO would this be useful? It'd be useful for testing...**
901
- > [!WARNING]
902
- > The following documentation on manually registering components is primarily applicable to those who are writing Laravel packages that include view components. If you are not writing a package, this portion of the component documentation may not be relevant to you.
903
-
904
- When writing components for your own application, components are automatically discovered within the `app/View/Components` directory and `resources/views/components` directory.
905
-
906
- However, if you are building a package that utilizes Blade components or placing components in non-conventional directories, you will need to manually register your component class and its HTML tag alias so that Laravel knows where to find the component. You should typically register your components in the `boot` method of your package's service provider:
907
-
908
- use Illuminate\Support\Facades\Blade;
909
- use VendorPackage\View\Components\AlertComponent;
910
-
911
- /**
912
- * Bootstrap your package's services.
913
- */
914
- public function boot(): void
915
- {
916
- Blade::component('package-alert', AlertComponent::class);
917
- }
918
-
919
- Once your component has been registered, it may be rendered using its tag alias:
920
-
921
- ```rblade
922
- <x-package-alert/>
923
- ```
924
-
925
754
  <a name="anonymous-index-components"></a>
926
755
  ### Index Components
927
756
 
@@ -949,64 +778,26 @@ However, when an `index.rblade` template exists in a directory, it will be rende
949
778
  /app/views/components/accordion/item.rblade
950
779
  ```
951
780
 
952
- <a name="accessing-parent-data"></a>
953
- ### Accessing Parent Data
954
- **TODO this? It might be complicated**
955
- Sometimes you may want to access data from a parent component inside a child component. In these cases, you may use the `@aware` directive. For example, imagine we are building a complex menu component consisting of a parent `<x-menu>` and child `<x-menu.item>`:
781
+ <a name="forms"></a>
782
+ ## Forms
956
783
 
957
- ```rblade
958
- <x-menu color="purple">
959
- <x-menu.item>...</x-menu.item>
960
- <x-menu.item>...</x-menu.item>
961
- </x-menu>
962
- ```
784
+ ### Old Input
963
785
 
964
- The `<x-menu>` component may have an implementation like the following:
786
+ The Rails `params` Hash is available in views and components. However, the `@old` directive is a useful shortcut that will output the old input value for a given key:
965
787
 
966
788
  ```rblade
967
- <!-- /resources/views/components/menu/index.rblade -->
968
-
969
- @props(['color' => 'gray'])
970
-
971
- <ul {{ $attributes->merge(['class' => 'bg-'.$color.'-200']) }}>
972
- {{ $slot }}
973
- </ul>
789
+ <input type="text" name="email" value="@old('email', user.email)">
974
790
  ```
975
791
 
976
- Because the `color` prop was only passed into the parent (`<x-menu>`), it won't be available inside `<x-menu.item>`. However, if we use the `@aware` directive, we can make it available inside `<x-menu.item>` as well:
792
+ The first parameter is the name of the previous input, and the second input is the default if the key isn't present in `params`. The previous example is the equivalent of calling `params.fetch`:
977
793
 
978
794
  ```rblade
979
- <!-- /resources/views/components/menu/item.rblade -->
980
-
981
- @aware(['color' => 'gray'])
982
-
983
- <li {{ $attributes->merge(['class' => 'text-'.$color.'-800']) }}>
984
- {{ $slot }}
985
- </li>
986
- ```
987
-
988
- > [!WARNING]
989
- > The `@aware` directive can not access parent data that is not explicitly passed to the parent component via HTML attributes. Default `@props` values that are not explicitly passed to the parent component can not be accessed by the `@aware` directive.
990
-
991
- <a name="forms"></a>
992
- ## Forms
993
-
994
- <a name="csrf-field"></a>
995
- ### CSRF Field
996
- **TODO I don't think we need this?**
997
- Anytime you define an HTML form in your application, you should include a hidden CSRF token field in the form so that [the CSRF protection](/docs/{{version}}/csrf) middleware can validate the request. You may use the `@csrf` Blade directive to generate the token field:
998
-
999
- ```rblade
1000
- <form method="POST" action="/profile">
1001
- @csrf
1002
-
1003
- ...
1004
- </form>
795
+ <input type="text" name="email" value="{{ params.fetch(:email, user.email) }}">
1005
796
  ```
1006
797
 
1007
798
  <a name="method-field"></a>
1008
799
  ### Method Field
1009
- **TODO add this**
800
+
1010
801
  Since HTML forms can't make `PUT`, `PATCH`, or `DELETE` requests, you will need to add a hidden `_method` field to spoof these HTTP verbs. The `@method` RBlade directive can create this field for you:
1011
802
 
1012
803
  ```rblade
@@ -1017,52 +808,8 @@ Since HTML forms can't make `PUT`, `PATCH`, or `DELETE` requests, you will need
1017
808
  </form>
1018
809
  ```
1019
810
 
1020
- <a name="validation-errors"></a>
1021
- ### Validation Errors
1022
- **TODO this**
1023
- The `@error` directive may be used to quickly check if [validation error messages](/docs/{{version}}/validation#quick-displaying-the-validation-errors) exist for a given attribute. Within an `@error` directive, you may echo the `$message` variable to display the error message:
1024
-
1025
- ```rblade
1026
- <!-- /resources/views/post/create.rblade -->
1027
-
1028
- <label for="title">Post Title</label>
1029
-
1030
- <input id="title"
1031
- type="text"
1032
- class="@error('title') is-invalid @enderror">
1033
-
1034
- @error('title')
1035
- <div class="alert alert-danger">{{ $message }}</div>
1036
- @enderror
1037
- ```
1038
-
1039
- Since the `@error` directive compiles to an "if" statement, you may use the `@else` directive to render content when there is not an error for an attribute:
1040
-
1041
- ```rblade
1042
- <!-- /resources/views/auth.rblade -->
1043
-
1044
- <label for="email">Email address</label>
1045
-
1046
- <input id="email"
1047
- type="email"
1048
- class="@error('email') is-invalid @else is-valid @enderror">
1049
- ```
1050
-
1051
- You may pass [the name of a specific error bag](/docs/{{version}}/validation#named-error-bags) as the second parameter to the `@error` directive to retrieve validation error messages on pages containing multiple forms:
1052
-
1053
- ```rblade
1054
- <!-- /resources/views/auth.rblade -->
1055
-
1056
- <label for="email">Email address</label>
811
+ Alternatively, you can use the dedicated directives for each method: `@put`, `@patch`, or `@delete`.
1057
812
 
1058
- <input id="email"
1059
- type="email"
1060
- class="@error('email', 'login') is-invalid @enderror">
1061
-
1062
- @error('email', 'login')
1063
- <div class="alert alert-danger">{{ $message }}</div>
1064
- @enderror
1065
- ```
1066
813
 
1067
814
  <a name="stacks"></a>
1068
815
  ## Stacks
@@ -1072,11 +819,11 @@ RBlade allows you to push to named stacks which can be rendered elsewhere in ano
1072
819
  ```rblade
1073
820
  @push('scripts')
1074
821
  <script src="/example.js"></script>
1075
- @endpush
822
+ @endPush
1076
823
  ```
1077
824
 
1078
- If you would like to `@push` content if a given boolean expression evaluates to `true`, you may use the `@pushIf` directive:
1079
- **TODO add this**
825
+ If you would like to `@push` content if a given boolean expression evaluates to `true`, you may use the `@pushif` directive:
826
+
1080
827
  ```rblade
1081
828
  @pushIf(shouldPush, 'scripts')
1082
829
  <script src="/example.js"></script>
@@ -1098,153 +845,11 @@ If you would like to prepend content onto the beginning of a stack, you should u
1098
845
  ```rblade
1099
846
  @push('scripts')
1100
847
  This will be second...
1101
- @endpush
848
+ @endPush
1102
849
 
1103
850
  // Later...
1104
851
 
1105
852
  @prepend('scripts')
1106
853
  This will be first...
1107
- @endprepend
1108
- ```
1109
-
1110
- <a name="rendering-blade-fragments"></a>
1111
- ## Rendering Blade Fragments
1112
- **TODO this?**
1113
- When using frontend frameworks such as [Turbo](https://turbo.hotwired.dev/) and [htmx](https://htmx.org/), you may occasionally need to only return a portion of a Blade template within your HTTP response. Blade "fragments" allow you to do just that. To get started, place a portion of your Blade template within `@fragment` and `@endfragment` directives:
1114
-
1115
- ```rblade
1116
- @fragment('user-list')
1117
- <ul>
1118
- @foreach ($users as $user)
1119
- <li>{{ $user->name }}</li>
1120
- @endforeach
1121
- </ul>
1122
- @endfragment
1123
- ```
1124
-
1125
- Then, when rendering the view that utilizes this template, you may invoke the `fragment` method to specify that only the specified fragment should be included in the outgoing HTTP response:
1126
-
1127
- ```php
1128
- return view('dashboard', ['users' => $users])->fragment('user-list');
1129
- ```
1130
-
1131
- The `fragmentIf` method allows you to conditionally return a fragment of a view based on a given condition. Otherwise, the entire view will be returned:
1132
-
1133
- ```php
1134
- return view('dashboard', ['users' => $users])
1135
- ->fragmentIf($request->hasHeader('HX-Request'), 'user-list');
1136
- ```
1137
-
1138
- The `fragments` and `fragmentsIf` methods allow you to return multiple view fragments in the response. The fragments will be concatenated together:
1139
-
1140
- ```php
1141
- view('dashboard', ['users' => $users])
1142
- ->fragments(['user-list', 'comment-list']);
1143
-
1144
- view('dashboard', ['users' => $users])
1145
- ->fragmentsIf(
1146
- $request->hasHeader('HX-Request'),
1147
- ['user-list', 'comment-list']
1148
- );
1149
- ```
1150
-
1151
- <a name="extending-blade"></a>
1152
- ## Extending Blade
1153
- **TODO this?**
1154
- Blade allows you to define your own custom directives using the `directive` method. When the Blade compiler encounters the custom directive, it will call the provided callback with the expression that the directive contains.
1155
-
1156
- The following example creates a `@datetime($var)` directive which formats a given `$var`, which should be an instance of `DateTime`:
1157
-
1158
- <?php
1159
-
1160
- namespace App\Providers;
1161
-
1162
- use Illuminate\Support\Facades\Blade;
1163
- use Illuminate\Support\ServiceProvider;
1164
-
1165
- class AppServiceProvider extends ServiceProvider
1166
- {
1167
- /**
1168
- * Register any application services.
1169
- */
1170
- public function register(): void
1171
- {
1172
- // ...
1173
- }
1174
-
1175
- /**
1176
- * Bootstrap any application services.
1177
- */
1178
- public function boot(): void
1179
- {
1180
- Blade::directive('datetime', function (string $expression) {
1181
- return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
1182
- });
1183
- }
1184
- }
1185
-
1186
- As you can see, we will chain the `format` method onto whatever expression is passed into the directive. So, in this example, the final PHP generated by this directive will be:
1187
-
1188
- <?php echo ($var)->format('m/d/Y H:i'); ?>
1189
-
1190
- > [!WARNING]
1191
- > After updating the logic of a Blade directive, you will need to delete all of the cached Blade views. The cached Blade views may be removed using the `view:clear` Artisan command.
1192
-
1193
- <a name="custom-echo-handlers"></a>
1194
- ### Custom Echo Handlers
1195
- **TODO this? Need to do something similar for attribute manager anyway**
1196
- If you attempt to "echo" an object using Blade, the object's `__toString` method will be invoked. The [`__toString`](https://www.php.net/manual/en/language.oop5.magic.php#object.tostring) method is one of PHP's built-in "magic methods". However, sometimes you may not have control over the `__toString` method of a given class, such as when the class that you are interacting with belongs to a third-party library.
1197
-
1198
- In these cases, Blade allows you to register a custom echo handler for that particular type of object. To accomplish this, you should invoke Blade's `stringable` method. The `stringable` method accepts a closure. This closure should type-hint the type of object that it is responsible for rendering. Typically, the `stringable` method should be invoked within the `boot` method of your application's `AppServiceProvider` class:
1199
-
1200
- use Illuminate\Support\Facades\Blade;
1201
- use Money\Money;
1202
-
1203
- /**
1204
- * Bootstrap any application services.
1205
- */
1206
- public function boot(): void
1207
- {
1208
- Blade::stringable(function (Money $money) {
1209
- return $money->formatTo('en_GB');
1210
- });
1211
- }
1212
-
1213
- Once your custom echo handler has been defined, you may simply echo the object in your Blade template:
1214
-
1215
- ```rblade
1216
- Cost: {{ $money }}
1217
- ```
1218
-
1219
- <a name="custom-if-statements"></a>
1220
- ### Custom If Statements
1221
- **TODO this**
1222
- Programming a custom directive is sometimes more complex than necessary when defining simple, custom conditional statements. For that reason, Blade provides a `Blade::if` method which allows you to quickly define custom conditional directives using closures. For example, let's define a custom conditional that checks the configured default "disk" for the application. We may do this in the `boot` method of our `AppServiceProvider`:
1223
-
1224
- use Illuminate\Support\Facades\Blade;
1225
-
1226
- /**
1227
- * Bootstrap any application services.
1228
- */
1229
- public function boot(): void
1230
- {
1231
- Blade::if('disk', function (string $value) {
1232
- return config('filesystems.default') === $value;
1233
- });
1234
- }
1235
-
1236
- Once the custom conditional has been defined, you can use it within your templates:
1237
-
1238
- ```rblade
1239
- @disk('local')
1240
- <!-- The application is using the local disk... -->
1241
- @elsedisk('s3')
1242
- <!-- The application is using the s3 disk... -->
1243
- @else
1244
- <!-- The application is using some other disk... -->
1245
- @enddisk
1246
-
1247
- @unlessdisk('local')
1248
- <!-- The application is not using the local disk... -->
1249
- @enddisk
854
+ @endPrepend
1250
855
  ```