Перейти к содержанию

Директива wire:drop⚓︎

wire:drop превращает любой элемент в зону перетаскивания. Он отслеживает перетаскивание объектов над элементом, отражает состояние перетаскивания, чтобы вы могли оформить оверлей, и вычисляет своё выражение, когда объект отпускается.

В отличие от обычного обработчика события drop, которое браузер не вызывает, пока вручную не отменено событие dragover, wire:drop самостоятельно управляет всем жизненным циклом перетаскивания.

Использование⚓︎

Самый распространённый вариант использования зоны перетаскивания — приём файлов. Для этого применяется модификатор .file вместе с действием $upload, которое загружает перетащенные файлы в свойство компонента:

resources/views/components/⚡photo-gallery.blade.php
<?php

use Livewire\Attributes\Validate;
use Livewire\WithFileUploads;
use Livewire\Component;

new class extends Component {
    use WithFileUploads;

    #[Validate(['photos.*' => 'image|max:10240'])]
    public $photos = [];
};
<div wire:drop.file="$upload('photos')">
    Перетащите файлы сюда
</div>

Модификатор .file ограничивает зону перетаскивания только случаями, когда перетаскиваются файлы, — при перетаскивании выделенного текста над элементом ничего не происходит. Перетащенные файлы проходят через стандартный механизм загрузки файлов: временные загрузки, валидацию, предпросмотры и полноценные объекты загрузки — всё работает точно так же, как если бы файлы были выбраны через поле выбора файлов.

Оформление состояния перетаскивания⚓︎

Пока объект перетаскивается над зоной перетаскивания, Livewire добавляет элементу атрибут data-dragging. Его можно использовать для оформления с помощью обычного CSS — никакого JavaScript не требуется:

<div wire:drop.file="$upload('photos')" class="border-dashed data-dragging:border-blue-500">
    Перетащите фотографии сюда
</div>

Или используйте in-*-варианты Tailwind для стилизации дочернего элемента:

<div wire:drop.file="$upload('photos')">
    <div class="opacity-0 in-data-dragging:opacity-100">
        Отпустите, чтобы загрузить
    </div>
</div>

При использовании .file этот атрибут появляется только при перетаскивании файлов, поэтому оверлей никогда не будет мигать, когда пользователь перетаскивает текст по странице.

Приём файлов, перетаскиваемых в любую область страницы⚓︎

Интерфейсы чатов и редакторов часто принимают файлы, перетаскиваемые в любую область окна, а не только в определённую зону. Добавьте модификатор .window, чтобы прослушивать события на уровне окна:

<div wire:drop.file.window="$upload('attachments')">
    { Полноэкранный оверлей, отображаемый, пока файлы перетаскиваются над страницей... }
    <div class="hidden in-data-dragging:grid fixed inset-0 place-items-center bg-black/50 text-white">
        Перетащите файлы, чтобы прикрепить их
    </div>

    { ... }
</div>

Атрибут data-dragging по-прежнему добавляется к элементу, на котором указан директива, поэтому у оверлея всегда есть элемент, к которому можно привязать стили.

Универсальные зоны перетаскивания⚓︎

Без .file директива wire:drop работает как универсальная зона перетаскивания: любое перетаскивание активирует её, а при отпускании объекта вычисляется указанное выражение. Событие drop при этом доступно через $event. Такой режим подходит для обработки объектов, не являющихся файлами, например текста, ссылок или изображений, перетаскиваемых из другой вкладки.

<div wire:drop="importFromUrl($event.dataTransfer.getData('text/uri-list'))">
    Перетащите ссылку сюда
</div>

Стоит знать о двух особенностях поведения по умолчанию:

  • Для файлов, перетаскиваемых в зону, стандартное поведение браузера всегда отменяется — ведь никто не ожидает, что при перетаскивании файла в приложение браузер покинет текущую страницу и откроет этот файл.
  • Для всех остальных объектов сохраняется стандартное поведение браузера (например, при перетаскивании текста в поле ввода он будет вставлен), если только ваше выражение не вызывает $event.preventDefault().

Загрузка файлов через универсальную зону перетаскивания тоже работает

$upload самостоятельно выполняет необходимую фильтрацию — при использовании обычного wire:drop="$upload('photos')" он загрузит перетащенные файлы и молча проигнорирует всё остальное. Используйте .file, если хотите, чтобы сама зона перетаскивания реагировала только на файлы, а data-dragging (и, соответственно, ваш оверлей) появлялся только при перетаскивании файлов.

Справочник⚓︎

wire:drop="expression"
Модификатор Описание
.file Ограничивает зону перетаскивания только случаями, когда перетаскиваются файлы: только при перетаскивании файлов появляется data-dragging, и только при их отпускании вычисляется выражение
.window Принимает объекты, перетаскиваемые в любую область страницы, а не только на этот элемент