All rules

Sheath rule

blade-component-tag-integrity

Component tags must stay compilable. Bound attributes cannot contain echoes, the attribute list cannot contain directives, and every <x-*> or <x:*> tag must be paired or self-closed.
Package
Core
Category
Blade
Default severity
error by default
Auto-fix
Auto-fix available

for echoes in bound attributes. See Auto-fix.

#Why

Blade component tags accept plain attributes, bound attributes, @class(...), @style(...), the :$var shorthand, and $attributes method chains such as {{ $attributes->whereStartsWith('wire:model') }}. The following unsupported forms break compilation or prevent Blade from recognizing the component.

  • An echo in a bound attribute: :message="{{ $msg }}". Bound values are already PHP expressions, so use :message="$msg" instead.
  • A directive in the attribute list: @if($x) type="a" @endif, or even the boolean helpers (@checked($v), @disabled($v)) that are documented for plain HTML elements. These directives prevent Blade from recognizing the tag as a component.
  • Any echo other than {{ $attributes... }} in attribute position. Other echoes also prevent the tag from being recognized as a component.
  • An <x-*> opener that never closes, or a </x-*> closer with no opener. Unclosed component tags can discard output, while stray closing tags produce an invalid component close.

All checks are limited to Laravel's x- and x: tags. Other prefixes (livewire:, flux:) compile through their own packages, whose rules differ.

#Examples

#Bad

<x-alert :message="{{ $msg }}" />
<x-alert @if($urgent) type="error" @endif />
<x-input @checked($value) />
<x-alert {{ $foo }} />
<x-alert>
<p>This opener is never closed; everything after it is lost.</p>
<p>Done.</p>
</x-alert>

#Good

<x-alert :message="$msg" />
<x-alert :type="$urgent ? 'error' : null" />
<x-input :checked="$value" />
<x-button @class(['p-4', 'font-bold' => $active]) @style(['color: red' => $hasError]) />
<x-alert {{ $attributes->merge(['class' => 'alert']) }} />
<x-input {{ $attributes->whereStartsWith('wire:model') }} />
<x-alert>
<p>Content</p>
</x-alert>
<input type="checkbox" @checked($value) />

#Auto-fix

When a bound attribute's value is exactly one echo and nothing else, auto-fix unwraps it while preserving the intended value:

{{-- before --}}
<x-alert :message="{{ $msg }}" />
{{-- after --}}
<x-alert :message="$msg" />

A bound value that mixes an echo with other text gets no fix because the intended expression cannot be inferred.

The other findings have no fix. Moving a directive out of a tag or pairing an unclosed tag requires a structural decision.

#Notes

  • The boolean helpers (@checked, @disabled, @selected, @readonly, @required) are documented for plain HTML elements and keep working there; it is only inside <x-*> tags that they break the tag. Bind the attribute (:checked="$value") instead. Component attribute bags render boolean attributes correctly from bound values.
  • Listener-shaped attributes such as @error="handler" can collide with Blade directive names. See blade-no-directive-attribute-collision.

#Related Rules