How to make a reusable click to copy button in Alpine.js in Laravel

Rezaul H Reza 28 December 2022 Component 4 minutes read

First, create a new Blade component in your resources/views/components directory. You can do this by running the following command:

php artisan make:component CopyButton

Open the newly created copy-button.blade.php file and define the component's template. We can delete the CopyButton.php class file, since we do not need that, we can define the props in our  view file. Moreover, we do not even need to define the props. I am including it here to showcase the mechanism. Anyways, You can use the following code as a starting point:

@props(['title' => 'Click To Copy','clipBoardText' => '', 'caption'=> 'Copy To Clipboard', 'copy'=> true]) <div class="flex" x-data="{ isVisible: {{ $copy === true ? 'true' : 'false' }}, copied: false, }" x-init="window.copyToClipboard.init()" @if ($copy === 'hover')@mouseleave="isVisible = false"@mouseover="isVisible = true" @endif x-cloak > {{ $slot }} @if ($copy) <div class="flex ml-1"> <button :class="[ isVisible ? 'visible btn btn-default btn-xs ml-2 mt-1' : 'invisible']" x-on:click=" copied = true; setTimeout(() => copied = false, 2000); " class="copy btn btn-default btn-sm" data-clipboard-text="{{ $clipboardText }}" title="{{ $title ?? '' }}" > <i class="fa fa-copy"></i> {{ $caption }} </button> <div x-cloak x-show="copied" class="absolute p-1 px-2 text-green bg-white"> <i class='ticked h-5 w-12'title="Copied!"></i> </div> </div> @endif </div> <script> window.copyToClipboard = { isInitialised: false, init() { if (this.isInitialised) { return } this.isInitialised = true new Clipboard('.copy', { text: function (trigger) { return trigger.getAttribute('data-clipboard-text'); } }).on('success', function (e) { e.clearSelection(); }) }, } </script>

  1. The component has two variables: clipboardText and copy. The clipboardText variable determines the text that will be copied to the clipboard when the button is clicked, and the copy variable determines whether the button is always visible, or if it only appears when the user hovers over the element.
  2. The component uses Laravel's Blade syntax and the x-data attribute to define a dynamic component that uses JavaScript to handle the copy-to-clipboard functionality. The x-init attribute is used to initialize the copy-to-clipboard functionality, which is defined in a separate JavaScript file.
  3. The component also has an @if directive that checks the value of the copy variable. If copy is set to 'hover', the component will only be visible when the user hovers over the element. Otherwise, the component will always be visible.

The component includes a button element with the copy class and the data-clipboard-text attribute set to the value of the clipboardText variable. When this button is clicked, the copied property of the data object is set to true, and a message is displayed to the user indicating that the text has been copied to the clipboard.

Now that you have created the component, you can include it in any of your views by passing in any necessary variables as named parameters. For example:

@props(['textToCopy' => 'Copy Me'])

<x-copy-button copy="hover" :clipboardText="$textToCopy"/>


This will include the component in your view and render the copy-to-clipboard button. Make sure to include the necessary JavaScript file and any other dependencies, and you should be good to go!

Related Posts

Create Vue 3 SlideOver dialog component with tailwind css 4 minutes read

Imagine you're on a website, and you want to show... Read more

Rezaul H Reza,16 August 2023
Drawing App using Vue 8 minutes read

Read more

Rezaul H Reza,28 January 2023
How to Copy Text wrapped in a <pre> tag to the Clipboard using JavaScript 5 minutes read

In this tutorial, we'll walk you through the steps... Read more

Rezaul H Reza,29 December 2022
Creating a Chart.js Component in Alpine.js and Livewire: A Step-by-Step Guide 8 minutes read

"In this tutorial, we will learn how to create a C... Read more

Rezaul H Reza,27 December 2022

Write a comment

Comments (0)