【问题标题】:Animating a re-ordered List with Livewire and Alpine JS使用 Livewire 和 Alpine JS 对重新排序的列表进行动画处理
【发布时间】:2022-01-11 16:21:35
【问题描述】:

我有一个 alpine js 和 livewire 组件,用于显示列表中的添加和删除项目。每个项目都显示为一个令牌。

这是令牌的 HTML 代码:

  <div
                    class="inline-block px-2 py-4"
                    x-data="{show : false}"
                    x-show="show"
                    x-init="setTimeout(() => {show=true}, 450)"
                    x-transition.duration.450>
                    <span class="px-4 py-3 space-x-1 rounded-full shadow bg-indigo-300 text-white font-light">
                        <span>{{ $item->name }}</span>
                        <span
                            class="font-bold text-xl cursor-pointer"
                            @click="show = false;
                                            setTimeout(() => {$wire.updateSelection({{ $item->id }})}, 400);">
                            &times;
                        </span>
                    </span>
                    <input type="text" name="clients[]" type="number" value="{{ $item->id }}" hidden />
                </div>

我需要令牌在从 DOM 中移除之前顺利消失。为了实现这一点,我尝试应用以下代码。

  @click="show = false; setTimeout(() => {$wire.updateSelection({{ $item->id }})}, 400);">

问题在于,一旦标记被隐藏,然后通过 livewire 方法从数组中删除,循环中的下一个标记仍然隐藏,因为它的 show 属性现在设置为 false。这是为什么呢?

这是一个演示:https://gfycat.com/brightbronzeherring

我尝试通过添加一个额外的 setTimeout 来修复它,但它运行不顺畅。使用此解决方案时,如果您决定删除最后显示的令牌,则会添加不需要的动画:

  @click="show = false; setTimeout(() => {$wire.updateSelection({{ $item->id }})}, 400); setTimeout(() => {show=true}, 300);">

这是livewire组件的php代码:

<?php

namespace App\Http\Livewire\Components;

use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Livewire\Component;

class ManyToManyDropdown extends Component
{
    public $selected;
    public $noUsers;
    public $link;


    // PTR add comments
    public function mount($link)
    {
        if (!empty($link)) { // when the form is used in the 'create' view we pass an empty string PTR

            $this->link = $link;
            $this->selected = $link->users; // load the users which have already been selected
            $this->noUsers = $this->selected->count() > 0 ? false : true; // determine if the 'no users message should be displayed'

        } else {

            $this->selected = new Collection();
            $this->noUsers = true;
        }

    }

    // PTR add comments
    public function updateSelection($id)
    {
        // validate the data
        $valid = User::all()->pluck('id')->contains($id);

        if (!$valid) { // if data validation fails - abort
            return abort(404);
        }


        // persis the data
        $found = $this->selected->pluck('id')->contains($id);

        $user = User::find($id);

        if ($found) { // in case the item is already in the collection we remove it

            $this->selected = $this->selected->filter(function ($item) use ($id) {
                return $item->id != $id;
            });

        } else { // in case the item is not in the collection then it is added

            $this->selected->push($user);
        }

        $this->noUsers = $this->selected->count() == 0 ? true :false ;  // check if a 'no items message should be shown'
    }

    // PTR add comments
    public function render()
    {
        return view('livewire.components.many-to-many-dropdown', [
            'users' => User::clients()->get()
        ]);
    }
}

这是 HTML:

<div class="space-y-4">
    <!-- Clients -->
    <div>

        <x-label class="font-bold" for="Client" :value="__('Client:')" />

        <div>

            @foreach ($selected as $item)

                <div
                    class="inline-block px-2 py-4"
                    x-data="{show : false}"
                    x-show="show"
                    x-init="setTimeout(() => {show=true}, 450)"
                    x-transition.duration.450>
                    <span class="px-4 py-3 space-x-1 rounded-full shadow bg-indigo-300 text-white font-light">
                        <span>{{ $item->name }}</span>
                        <span
                            class="font-bold text-xl cursor-pointer"
                            @click="show = false;
                            setTimeout(() => {$wire.updateSelection({{ $item->id }})}, 400);
                            setTimeout(() => {show=true}, 300);">
                            &times;
                        </span>
                    </span>
                    <input type="text" name="clients[]" type="number" value="{{ $item->id }}" hidden />
                </div>

            @endforeach

        </div>



        {{-- message in case there are not users selcted for this link --}}
        <div x-data="{show: @entangle('noUsers')}" x-show="show" x-transition.duration.450ms
            class="mt-1 px-2 py-2 cursor-not-allowed text-sm rounded-md shadow-sm border border-gray-400 itlaic font-hairline">
            There are no customers selected...
        </div>

    </div>

    <!-- Dropdown -->
    <div>
        <x-label class="font-bold" :value="__('Assign to:')" />


        <div x-data="{show:false}" class="mt-1 relative">

            <button
                @click="show = !show;" type="button"
                class="relative w-full bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-300 focus:border-indigo-500 sm:text-sm"
                aria-haspopup="listbox"
                aria-expanded="true"
                aria-labelledby="listbox-label">
                <span x-ref="button" class="block truncate">
                    Select users...
                </span>
                <span class="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
                    <!-- Heroicon name: solid/selector -->
                    <svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
                        fill="currentColor" aria-hidden="true">
                        <path fill-rule="evenodd"
                            d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"
                            clip-rule="evenodd" />
                    </svg>
                </span>
            </button>


            <ul x-show="show" x-transition:enter="transition ease-out duration-300" x-transition:enter-start="opacity-0"
                x-transition:enter-end="opacity-100" @click.away='show = false'
                class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
                tabindex="-1" role="listbox" aria-labelledby="listbox-label" aria-activedescendant="listbox-option-3">

                @foreach ($users as $user)

                    {{-- in case the array contains tha user I remove it, otherwise I add it --}}
                    <li x-data="{showCheck : false}" @click="showCheck = !showCheck"
                        wire:click="updateSelection('{{ $user->id }}')"
                        class="text-gray-900 cursor-default select-none relative py-2 pl-8 pr-4 hover:bg-blue-300 hover:text-white"
                        role="option">
                        <span class="font-normal block truncate">
                            {{ $user->name }}
                        </span>


                        <span x-show="showCheck" x-transition.duration.400ms
                            class="text-indigo-600 absolute inset-y-0 left-0 flex items-center pl-1.5">
                            <!-- Heroicon name: solid/check -->
                            <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
                                fill="currentColor" aria-hidden="true">
                                <path fill-rule="evenodd"
                                    d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
                                    clip-rule="evenodd" />
                            </svg>
                        </span>
                    </li>

                @endforeach

            </ul>
        </div>
    </div>
</div>

【问题讨论】:

    标签: laravel laravel-livewire alpine.js


    【解决方案1】:

    缺少wire:key={{$item-&gt;id}}

    在视图中实现@foreach

    更多信息可以在这里找到:

    【讨论】:

      猜你喜欢
      • 2015-12-01
      • 2015-01-27
      • 2021-06-05
      • 2011-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多