บทความ

Livewire wire:confirm ใช้ยังไง ให้ยืนยันก่อนลบหรือ Submit ข้อมูล

ใส่ wire:confirm คู่กับ wire:click หรือ wire:submit แล้ว Livewire จะถามผู้ใช้ก่อนเรียก action ให้เอง และใช้ .prompt บังคับให้พิมพ์คำยืนยันก่อนลบได้ โดยไม่ต้องเขียน JavaScript

เผยแพร่
อัปเดต
— ปรับให้ตรงกับ Livewire 4 เพิ่มการใช้กับ wire:submit
เวลาอ่าน
2 นาที
แปลจาก
Paul Redmond · laravel-news.com
แท็ก
#Laravel#Livewire

ปุ่มลบหรือปุ่มที่ย้อนกลับไม่ได้ ควรถามผู้ใช้ก่อนสักครั้ง ใน Livewire เราใส่ directive wire:confirm ไว้บนปุ่ม แล้ว Livewire จะเปิดกล่องยืนยันของเบราว์เซอร์ให้ก่อนเรียก action ทำงานเหมือน confirm() ของ JavaScript โดยเราไม่ต้องเขียน JavaScript เองเลย

ถ้าเขียนด้วย JavaScript เอง ก็จะได้ประมาณนี้

if (window.confirm("ยืนยันว่าจะลบผู้ใช้คนนี้จริง ๆ นะ?")) {
    // ยืนยันแล้ว ลบได้เลย
}

Livewire ให้เราเรียกกล่องยืนยันได้สองแบบ คือกด OK หรือ Cancel กับให้พิมพ์คำยืนยัน

กด OK หรือ Cancel ก่อนเรียก action

ใส่ wire:confirm คู่กับ directive ที่เรียก action อย่าง wire:click แล้วเขียนข้อความที่จะถามไว้ในค่าของ wire:confirm

<div>
    <h2>Danger zone</h2>
    <button
        type="button"
        wire:click="delete"
        wire:confirm="Are you sure you want to delete this project?"
    >
        Delete this project
    </button>
</div>

พอกดปุ่ม Livewire จะเปิดกล่องยืนยันของเบราว์เซอร์ขึ้นมา ถ้ากด OK ก็เรียก method delete() ใน component ตามปกติ ถ้ากด Cancel หรือกด Esc ก็ไม่มีอะไรเกิดขึ้น ถ้าใส่ wire:confirm เฉย ๆ ไม่มีข้อความ กล่องจะถามว่า "Are you sure?"

กล่องยืนยันของเบราว์เซอร์ถามว่า Are you sure you want to delete this project? พร้อมปุ่ม Cancel และ OK

กดปุ่ม Delete this project แล้ว Livewire เปิดกล่อง confirm() ของเบราว์เซอร์ให้

ให้ผู้ใช้พิมพ์คำยืนยันก่อนลบ ด้วย .prompt

ถ้าเป็นข้อมูลสำคัญจริง ๆ เราอยากให้ผู้ใช้พิมพ์คำยืนยันก่อน แบบเดียวกับตอนลบ repository ใน GitHub ทีนี้ก็ต่อ modifier .prompt ท้าย wire:confirm

<div>
    <h2>Danger zone</h2>
    {{-- ... --}}
    <button
        type="button"
        wire:click="delete"
        wire:confirm.prompt="Are you sure?\n\nType DELETE to confirm|DELETE"
    >
        Delete this project
    </button>
</div>

ค่าของ .prompt มีสองท่อน คั่นด้วย | ท่อนหน้าคือข้อความที่จะถาม ท่อนหลังคือคำที่ผู้ใช้ต้องพิมพ์ให้ตรง ส่วน \n ในข้อความคือขึ้นบรรทัดใหม่

พอกดปุ่ม เบราว์เซอร์จะเปิดกล่อง prompt() ให้ผู้ใช้พิมพ์ ต้องพิมพ์ DELETE ตรงทุกตัวอักษร รวมถึงตัวพิมพ์ใหญ่เล็ก Livewire ถึงจะเรียก delete() ให้ ถ้าพิมพ์ไม่ตรงหรือกด Cancel ก็ไม่เกิดอะไรขึ้น

ใช้ชื่อโปรเจกต์เป็นคำยืนยัน

คำยืนยันเป็นค่าจาก component ก็ได้ เช่นให้พิมพ์ชื่อโปรเจกต์เป็นตัวพิมพ์ใหญ่ก่อนลบ เครื่องหมายคำพูดในข้อความต้องเขียนเป็น &quot; เพราะอยู่ใน attribute ของ HTML

<div>
    <h2>Danger zone</h2>
    {{-- ... --}}
    <button
        type="button"
        wire:click="delete"
        wire:confirm.prompt="Are you sure?\n\nType &quot;{{ str($project_name)->upper() }}&quot; to confirm|{{ str($project_name)->upper() }}"
    >
        Delete this project
    </button>
</div>

ใช้กับฟอร์มที่ส่งด้วย wire:submit

wire:confirm ใช้กับ wire:submit ได้ด้วย แต่ต้องใส่ไว้บน <form> ตัวเดียวกับ wire:submit ไม่ใช่บนปุ่ม submit

<form wire:submit="save" wire:confirm="ส่งใบสั่งซื้อนี้เลยไหม? ส่งแล้วแก้ไม่ได้">
    <input type="text" wire:model="note">

    <button type="submit">ส่งใบสั่งซื้อ</button>
</form>

กล่องยืนยันกันแค่มือพลาด ฝั่ง server ยังต้องเช็คสิทธิ์

wire:confirm ทำงานในเบราว์เซอร์อย่างเดียว ผู้ใช้เรียก public method ของ component จาก DevTools ได้โดยไม่ผ่านกล่องนี้ ใน delete() เราจึงยังต้องเช็คสิทธิ์เองเสมอ ตามที่เอกสารของ Livewire เตือนไว้

public function delete(): void
{
    $this->authorize('delete', $this->project);

    $this->project->delete();
}

อยากได้ modal ที่แต่งได้ ใช้ Flux หรือ Filament

กล่อง confirm() กับ prompt() หน้าตาเปลี่ยนตามเบราว์เซอร์ แต่งสีหรือเปลี่ยนข้อความบนปุ่มไม่ได้ ถ้าอยากได้ modal ที่เข้ากับหน้าเว็บ มีทางที่ไม่ต้องเขียนเองดังนี้

  • Flux ชุด UI ของทีม Livewire มี component flux:modal อยู่ในรุ่นฟรี
  • ถ้าใช้ Filament อยู่แล้ว ต่อ ->requiresConfirmation() ท้าย Action ก็ได้ modal ยืนยันทันที ดูเอกสารของ Filament

รายละเอียดทั้งหมดของ wire:confirm อ่านต่อได้ที่เอกสารของ Livewire

อ่านต่อ

ล่าสุด

ดูทั้งหมด →