Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

MrMoto9000's avatar

Laravel Blade Components... Best practice for props?

There's a great Livewire tutorial on Laracasts by Kevin McKee where he gives an example of using Laravel components for form elements. His example looks like this:

<x-text-input
    wire:model="name"
    type="text"
    label="name"
    :required="true"
    placeholder=""
    class="" />

And the actual component file:

@props([
    'text' => "text"
    'label' => ""
    'required' => false
    'placeholder' => ""
])

<div class="{!! $attributes !!}">
  <label for="email">{{ $label }}</label>
  <input id="email"
    type="{{ $type }}"
    required="{{ $type }}"
    placeholder="{{ $placeholder }}">

etc.

Whereas Laravel Breeze follows the same pattern, but implements it far more simply:

<x-input 
    id="email" 
    class="block mt-1 w-full" 
    type="email" 
    name="email" 
    :value="old('email')" 
    required 
    autofocus />

And the actual component file:

@props(['disabled' => false])

<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'rounded-md shadow-sm border-gray-300']) !!}>

What's the reason for Kevin McKee's approach, when you could simply ignore @props and they would pass through to the rendered HTML anyway (as with Laravel Breeze's approach)?

Edit: Ignore the above question. It totally makes sense now. Still don't understand the following, though:

And why does Laravel Breeze use disabled as a @prop when it could easily be passed through in the same way required and autofocus are?

0 likes
2 replies
martinbean's avatar

@johnnyw2001 The first example has the limitation that the only things you can set are what are in the props. So with that example, I can’t set the input to be disabled, or add autofocus, or additional attributes for other input types such as min and max, or add any data- attributes or aria- attributes. Whereas Jetstream’s, any attributes I pass to the component are applied. So for this reason, Jetstream’s is far more usable that the first.

My own input Blade component looks like this:

@props(['id' => null, 'name'])

<input {{ $attributes->class(['form-control'])->merge(['id' => $id ?? $name, 'name' => $name, 'type' => 'text']) }}>

It automatically adds Bootstrap’s form-control class (you can change this to be Tailwind or whatever), and requires just a name by default. Any other attribute I pass when creating the component, will be passed to the component.

MrMoto9000's avatar

@martinbean That was my fault. I missed off the $attributes bag. I see now that props allow you to easily place HTML attributes wherever you'd like around a more complex component. And also make things a bit more readable if you want to use default values.

I still don't understand why disabled gets special treatment in the Laravel Breeze component, though?

Please or to participate in this conversation.