Skip to content

[12.x] Add InteractsWithData trait to ComponentAttributeBag #56452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

KennedyTedesco
Copy link
Contributor

This PR adds the InteractsWithData trait to ComponentAttributeBag, giving developers cleaner ways to work with Blade component attributes.

Why this change?

Working with component attributes currently requires a lot of boilerplate:

// Checking if attribute has a value
if (($attributes->get('data-progress') ?? '') !== '') {
    // ...
}

// Converting to boolean
$isExpanded = in_array($attributes->get('data-expanded'), ['true', '1', 'on', 'yes'], true); // Or using filter_var()

// Getting integers with defaults
$maxItems = is_numeric($attributes->get('data-max-items')) ? (int) $attributes->get('data-max-items') : 5;

What's new?

By reusing InteractsWithData, we gain many powerful methods.

✅ Simple validation methods

{{-- Check if attribute has a value --}}
@if ($attributes->filled('data-tooltip'))
    <span data-tooltip="{{ $attributes->get('data-tooltip') }}">
@endif

{{-- Check multiple attributes at once --}}
@if ($attributes->anyFilled(['data-image-src', 'data-video-url']))
    <div class="media-container">...</div>
@endif

🎯 Type casting that just works

{{-- Boolean conversion --}}
<dialog @if($attributes->boolean('data-modal-open')) open @endif>

{{-- Integer with default --}}
<div data-carousel-slides="{{ $attributes->integer('data-slides-count', 3) }}">

{{-- String as Stringable --}}
<h1 data-heading-level="{{ $attributes->string('data-level')->lower() }}">

{{-- Even enums! --}}
<div data-theme="{{ $attributes->enum('data-color-scheme', ThemeEnum::class)?->value }}">

🌟 Card component with dynamic link

{{-- Before: Messy conditional logic --}}
@if (($attributes->get('href') ?? '') !== '')
    <a href="{{ $attributes->get('href') }}" class="card-wrapper">
        <div class="card-content">{{ $slot }}</div>
    </a>
@else
    <div class="card-wrapper">
        <div class="card-content">{{ $slot }}</div>
    </div>
@endif

{{-- After: Clean and readable --}}
@if ($attributes->filled('href'))
    <a {{ $attributes->only(['href', 'target', 'rel'])->class('card-wrapper') }}>
        <div class="card-content">{{ $slot }}</div>
    </a>
@else
    <div {{ $attributes->except(['href', 'target', 'rel'])->class('card-wrapper') }}>
        <div class="card-content">{{ $slot }}</div>
    </div>
@endif

@taylorotwell
Copy link
Member

Are there slight breaking changes here around dot notation since the previous example uses array_key_exists and InteractsWithData uses Arr::has for example.

@KennedyTedesco
Copy link
Contributor Author

Hey @taylorotwell, that's a good concern and very well pointed out.

However, I couldn't find any case where this would be an issue for us, because ComponentAttributeBag will always have HTML attributes as string values, so there shouldn't be nested arrays. PHP arrays as values will become a @prop and will not be in the component's attributes bag.

Can we have someone else double-check my assumptions? (This person could be you, of course. :D) I've also submitted some more unit tests to validate if we're handling attributes with dots correctly.

In any case, I'm open to making the required changes, like keeping the original has() and hasAny() code. But, right now, I can't see how this could be an issue for us.

@taylorotwell taylorotwell merged commit 95d6542 into laravel:12.x Jul 30, 2025
60 checks passed
@KennedyTedesco KennedyTedesco deleted the 12x-component-attribute-bag-filled branch July 30, 2025 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants