# Reusable components

  • In this section, we will DRY up our code by using reusable Blade components
  • Blade components allow us to follow the DRY or “Don’t Repeat Yourself” principle which means that we can reuse the component anywhere in our application
  • In a previous chapter we were already introduced to (static) Blade components, but now we are going to make them dynamic
  • Laravel has two types of components:
    • components with a dedicated class: e.g. the layout component
    • components without a class (anonymous components): e.g. the navigation and footer in the layout
  • In this chapter we generate some anonymous components that we will use later in the course

REMARKS

  • Anonymous components MUST be placed inside the resources/views/components folder and be rendered with the x- prefix, followed by the path and name of the Blade file
  • The path and name are separated by a dot
  • When an index.blade.php file exists for the component, it will be rendered as the "root" node of the component
component Render
resources/views/components/list.blade.php <x-list>
resources/views/components/list/index.blade.php <x-list>
resources/views/components/alert.blade.php <x-alert>
resources/views/components/alert/index.blade.php <x-alert>
resources/views/components/alert/icon.blade.php <x-alert.icon>
  • We create our components in a subfolder resources/views/components/tmk (Thomas More Kempen 😉) so that we can be sure that they will not be overwritten if you later install any online component libraries

TIP

  • Create a (temporary) playground page (resources/views/playground.blade.php) that we can use to test our components
  • Create a route to the playground page in routes/web.php

# List component

  • Open http://vinyl_shop.test/admin/records (opens new window) in the browsers and look at the layout of the records list
  • Tailwind by default removes all styles from the unordered list, so we have to add additional classes to bring back the "look" of an unordered list
  • We're probably going to use a list multiple times in the application, so we'll have to add the styles over and over again (not really DRY...)
  • Such a list is a good candidate to convert to a component
  • Create a new list component inside the components folder: resources/views/components/tmk/list.blade.php
  • Open resources/views/admin/records/index.blade.php and add four list variants inside a Tailwind grid
  • Add an unordered list with a default slot to the list component
  • Style the ul tag as a bullet list

# Pass attributes to the component

  • Sometimes you may need to specify additional HTML attributes (title, class, ...) to the component
  • All attributes are available inside the attributes bag, but you have to add it explicitly (with $attributes) to the component

# Merging the class attribute

  • Most times you specify default classes inside the component and add additional classes on the class attribute of the component
  • These classes are not automatically merged with each other!
  • To solve this problem, we have to merge both class attributes together inside the component

# Pass data properties to the component

  • You may specify which attributes should be considered data variables or properties (instead of 'normal' attributes) using the @props directive at the top of the component
  • Properties also can have default values
  • Let's add a type property to specify the layout of the list
  • The type property can have the value:
    • ul: rendered as a numbered list (default value)
    • ol: rendered as a bullet list
    • group: rendered as a grouped list

# Section component

  • Let's create a component that renders a section with a white background, a tiny border and a drop shadow
  • This component is very simple, because it only contains a $slot and some basic styling
  • Create a new section component inside the components folder: resources/views/components/tmk/section.blade.php
  • Open resources/views/playground.blade.php and add three sections to the page

# Icons

  • When we created our project, we also installed the Blade UI kit icons.
  • These icons are also built as components and can be used in the same way as all other components.
  • Let's add, for example, the Fontawesome Home icon to page
  • Open resources/views/playground.blade.php and add four list variants inside a Tailwind grid

REMARK

  • Those icons are not visible in the resources/views/components/ folder.
  • They are hidden inside the vendor folder.

# Preloader component

  • A preloader is often used to indicate that the data from an external source (API) is being loaded
  • This preloader component is a very simple component with only class merging, a spinning icon (opens new window) and a default slot
  • Create a new preloader component inside the components folder: resources/views/components/tmk/preloader.blade.php
  • Open resources/views/playground.blade.php and add three preloaders to the page

# Alert component

  • The alert component has the following properties:
Property default description
type success The type (color) of the alert component
dismissible true Whether the component can be dismissed
closeSelf 0 Close the component automatically after x ms
  • Create a new alert component inside the components folder: resources/views/components/tmk/alert.blade.php
  • Open playground.blade.php and add four alert variants inside section

# Default component with 'type' property

# Add the 'dismissible' functionality

# Add the 'closeSelf' functionality

# Make it Livewire compatible

  • One of the issues with Livewire is that the component will not always react after the DOM has changed
  • When you close the alert and want to open it again, you need to re-initialize the component
  • Line 2: this can be solved by adding the wire:key Livewire directive with a unique (= random) value to the component

 


















<div
    wire:key="{{ rand() }}"
    {{ $attributes->merge(['class' => "$style flex gap-4 p-4 my-4 rounded border"]) }}
    x-data="{open: true}"
    x-show="open"
    x-transition.duration.300ms
    @if($closeSelf > 0)
        x-init="setTimeout(() => open = false, {{ $closeSelf }})"
    @endif
>
    <div class="flex-1">
        {{ $slot  }}
    </div>
    @if($dismissible)
        <div class="w-6 h-6 flex-none cursor-pointer {{ $style }}" @click="open = false">
            <x-heroicon-s-x-circle/>
        </div>
    @endif
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# Switch component (advanced)

  • The switch component is a toggle component that can be used to replace a regular checkbox
  • Because the default attributes for a checkbox (name, value, disabled, etc) must be moved from the root element of the component (label) to the nested input tag, you must pass the attributes to the switch component as props
  • The switch component has the following properties:
Property default description
checked false whether the checkbox is checked or not
disabled false whether the checkbox is disabled or not
name null the name of the checkbox
value null the value of the checkbox
colorOff bg-gray-200 the background color when the checkbox is not checked
colorOn bg-green-200 the background color when the checkbox is checked
textOff the text inside the switch when the checkbox is not checked
textOn the text inside the switch when the checkbox is checked
  • Create a new switch component inside the components folder: resources/views/components/tmk/form/switch.blade.php
  • Open resources/views/playground.blade.php and add four switch variants to the page

# Jetstream components

  • Jetstream components are a set of components that are built on top of the Jetstream (opens new window) package that we us later in this course for authentication
  • After publishing the component, you can use them in your own Blade files and you can eventually change them to your liking
  • Open the terminal and run the command php artisan vendor:publish --tag=jetstream-views
  • The Jetstream components are stored inside the resources/views/vendor/jetstream/components directory
  • All the Jetstream components have their own <x-jet-...> prefix
  • Jetstream has a lot of form-related components (input, button, error message, ...), but two of them are missing:
    • a select component
    • a textarea component
  • We create these components ourselves, but based on the input component so we have the same look and feel for every element in a form

# Select and textarea component

  • Create a new select component inside the components' folder: resources/views/components/tmk/form/select.blade.php
  • Create a new textarea component inside the components' folder: resources/views/components/tmk/form/textarea.blade.php
  • Open resources/views/playground.blade.php and add a form to the page

# Customizing the Jetstream button component

  • The button component is a simple component that is used to create a button, but it has only one color
  • Let's add a color property to change the color of the button:
    • color="dark": gray (default)
    • color="success": green (default)
    • color="danger": red
    • color="info": blue
  • Also add a disabled property to disable the button
    • If the property exists and is set to true, the disabled property is added to the <button> tag
    • If the property doesn't exist or is set to false, the disabled property is not included on <button> tag
  • Open resources/views/playground.blade.php and add four buttons to the page

# Logo component

  • Jetstream use three different logos for the admin panel
  • Let's create a new logo component that we will use on the navigation bar and on the admin panel
  • Create a new logo component inside the components folder: resources/views/components/tmk/logo.blade.php
  • Open resources/views/playground.blade.php and add three logos to the page

# Passing dynamic data to components

  • Hard coded, string values may be passed to the component using simple HTML attribute strings
  • You can also pass a dynamic values to the component, but than you have to prefix the attribute with :
  • Open resources/views/playground.blade.php and add two alerts to the page
Last Updated: 1/23/2023, 4:59:33 AM