laravellaravel-bladelaravel-components

$attributes->merge : what am i doing wrong


I have the following blade component in laravel. I am using tailwind. located in views/components/indigo-button-sm.blade.php

<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex justify-center py-1 px-1 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500']) }}>
    {{ $slot }}
</button>

I want to be able to change the component on the fly a bit. That is, i use the above component to show a "save" button. But then I want to show a button that says "confirm" your entry and change the look of the button slightly to hint visually that this is a different choice.

specifically, i have an autocomplete and the user is entering in an item that I am providing over 2,000 choices (schools). But if the user types in a school that is not in my database table list, I want them to confirm that they typed their school in correctly, so i want to show the "Confirm" your entry button, just to make sure. If they choose a school that is already in the list, I will not ask them to confirm their typing.

So, I want to change the save button

bg-indigo-600 hover:bg-indigo-700

to the Confirm button with a slightly different color scheme.

bg-indigo-800 hover:bg-indigo-900

or

<x-indigo-button-sm x-show="showsaveschool" wire:click="saveSchoolInfo">Save</x-indigo-button-sm>
<x-indigo-button-sm x-show="showconfirmschool" wire:click="confirmSaveSchoolInfo">Confirm</x-indigo-button-sm>

so they type in the school and the school is not in the lookup list. They click the Save button. The save button disappears and the confirm button shows and a piece of text will show up just below the confirm button.

As I type this, I am beginning to think it will be better to just create a Confirm button and always use it.

any way. I thought $attributes(merge['']) would allow you to change attributes, but I think it only allow syou to add attributes. So if you have a margin class, say "my-0" in the component, it doesn't seem to allow for a new similar class such as "my-5"

Your comments would be appreaciated.


Solution

  • For the class attribute, you can use conditional merging to ensure that you only insert the attribute if a conflicting one hasn't been set. The class() method is passed an array. If the array entry has a numeric index, the value is always merged into the class attribute. But if the entry has a non-numeric index, the index is merged into the class attribute if the value is true.

    <button
        {{ $attributes->class([
              'inline-flex justify-center py-1 px-1',
              'border border-transparent shadow-sm',
              'text-sm font-medium rounded-md text-white',
              'focus:outline-none focus:ring-2',
              'focus:ring-offset-2 focus:ring-indigo-500'
              'bg-indigo-600 hover:bg-indigo-700' => hasCustomBackground(),
           ])
           ->merge([
              'type' => 'button',
           ])
        }}
    >
        {{ $slot }}
    </button>
    

    Then, create a hasCustomBackground() component method based on the passed class value:

    class IndigoButtonSm extends Component
    {
        public string class;
    
        /**
         * Checks if the class attribute contains "bg-indigo"
         */
        public function hasCustomBackground(): bool
        {
            $classes = collect(explode(" ", $this->class));
            return $classes->contains(fn ($c) => str_contains("bg-indigo", $c));
        }
    
        ...
    }
    

    I've never used this functionality before, but based on the documentation it should work?