Кнопка переключения с блейд-компонентами и alpine.js

#laravel #laravel-blade #tailwind-css #alpine.js

#laravel #laravel-блейд #попутный ветер-css #alpine.js

Вопрос:

Я пытаюсь создать свой собственный компонент переключения. Этот компонент должен вести себя как обычный <input type="checkbox" > . До сих пор я создал следующее:

toggle.blade.php

 @props([
    'id' => 1
])

<div class="flex justify-center items-center">
    <div {{ $attributes->whereStartsWith('class')->merge(['class' => 'relative rounded-full transition duration-200 ease-linear' ]) }}
        :class="[ $refs.toggle{{ $id }}.checked ? 'bg-green-400' : 'bg-gray-400' ]">
        <label for="toggle{{ $id }}"
            class="absolute left-0 bg-white border-2 mb-2 w-1/2 h-full rounded-full transition transform duration-100 ease-linear cursor-pointer"
            :class="[ $refs.toggle{{ $id }}.checked ? 'translate-x-full border-green-400' : 'translate-x-0 border-gray-400' ]"></label>
        <input x-ref="toggle{{ $id }}" type="checkbox" id="toggle{{ $id }}" class="appearance-none w-full h-full active:outline-none focus:outline-none"
            {{ $attributes }} x-init="console.log('test')" />
    </div>
</div>
  

Как я это называю:

 <div>
  <x-inputs.toggle class="w-8 h-4" value="{{ $permission['id'] }}" 
    id="{{ $permission['id'] }}" x-model="permissions" /> <-- this one
  <input class="form-checkbox" value="{{ $permission['id'] }}" type="checkbox" x-model="permissions">
</div>
  

Я хочу иметь возможность поместить x-model в свой компонент. Чтобы я мог использовать обычную двустороннюю привязку из ввода флажка.

Приведенный выше код работает, но потому, что ссылка (ввод) инициализируется позже, чем $refs вызовы. Вызывая неправильные классы в переключателе, пока не будет нажат один из флажков / переключателей (ссылки обновлены), см. Изображение:

Флажки / переключатели для разрешения загрузки

Обычно я бы просто предоставил компоненту x-данные и проверил, не переключен ли он и т.д. Но тогда я не могу использовать x-model, потому что модель не существует в свойстве x-data компонента.

Что я также пробовал, так это передавать значение x-model в свойстве класса, например: :class="[ {{ $attirubtes->whereStartsWith('x-model')->first() ? ... : ... ]" . Но это тоже не работает, потому что я передаю массив в флажок x-model, где alpine.js делает какие-то необычные вещи и правильно с этим справляется.

Есть идеи, как я могу решить эту проблему?

Заранее спасибо.

Ответ №1:

Вы почти на месте. Это немного сложно, не видя вашего x-data , но используя refs вы как бы проходите долгий путь, вместо того, чтобы использовать встроенную реактивность, поэтому вы видите отложенное обновление.

Я думаю, вы сказали, что ваша permissions переменная является массивом. Если это так, вы можете получить имя переменной alpine и значение вашего флажка в блейд-компоненте и использовать их, чтобы определить, следует ли устанавливать флажок.

В блейд-компоненте

 <?php
    // Here we get the name of your alpine variable and the
    // value for the toggle
    $alpineVar = $attributes->whereStartsWith('x-model')->first();
    $value = $attributes->whereStartsWith('value')->first();
    
    // Here we build the javascript expression used to check
    // our permissions array for the toggle value
    $expression = "$alpineVar.includes('$value')";
?>

<div class="flex justify-center items-center">
    <div 
    {{ $attributes->whereStartsWith('class')->merge(['class' => 'relative rounded-full transition duration-200 ease-linear' ]) }}
    :class="[
        {{ $expression }} ? 'bg-green-400' : 'bg-gray-400'
    ]">
        <label 
        for="toggle{{ $id }}"
        class="absolute left-0 bg-white border-2 mb-2 w-1/2 h-full rounded-full transition transform duration-100 ease-linear cursor-pointer"
        :class="[
            {{ $expression }} ? 'translate-x-full border-green-400' : 'translate-x-0 border-gray-400'
        ]"></label>
        <input id="toggle{{ $id }}" type="checkbox" class="appearance-none w-full h-full active:outline-none focus:outline-none" {{ $attributes }} />
    </div>
</div>
  

Здесь мы получаем имя переменной экземпляра AlpineJs из вашего x-model атрибута и используем его для проверки наличия value в массиве, чтобы мы могли переключаться между классами в элементах div и label .

На странице

 <div 
x-data="{
    permissions: ['view','read','create']
}">
    <x-inputs.toggle class="w-8 h-4" value="view" x-model="permissions" />
</div>
  

Я, очевидно, использую x-data здесь пример экземпляра, поэтому настройте его в соответствии с вашими потребностями. Здесь мы передаем значение view , найденное в permissions объекте и связанное с x-model, чтобы дать нам необходимую реактивность.

Я надеюсь, что все имеет смысл и отвечает на ваш вопрос 👍🏼