Copying text to the clipboard in a Blazor application

  • Gérald Barré

Many websites provide a button to copy a value to the clipboard. For instance, after generating a token on Azure, you can copy the token to the clipboard:

A browser provides an API to write to the clipboard or read from it. Modern browsers implements navigator.clipboard to access the clipboard.

source: https://caniuse.com/#feat=mdn-api_clipboard_readtext

You can call these methods using IJSRuntime. Instead of using the runtime directly in your components, you can create a service to manage the clipboard.

using System.Threading.Tasks;
using Microsoft.JSInterop;

public sealed class ClipboardService
{
    private readonly IJSRuntime _jsRuntime;

    public ClipboardService(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    public ValueTask<string> ReadTextAsync()
    {
        return _jsRuntime.InvokeAsync<string>("navigator.clipboard.readText");
    }

    public ValueTask WriteTextAsync(string text)
    {
        return _jsRuntime.InvokeVoidAsync("navigator.clipboard.writeText", text);
    }
}

Then, you can register the service in the Program.cs file or Startup.cs:

builder.Services.AddScoped<ClipboardService>();

Finally, you can use the service in your component:

@page "/"
@inject ClipboardService ClipboardService

<h1>Demo Clipboard!</h1>

<button @onclick="ReadFromClipboard">Read from clipboard</button>
<button @onclick="CopyToClipboard">Copy to clipboard</button>
@text

@code {
    string text;

    async Task ReadFromClipboard()
    {
        // Reading from the clipboard may be denied, so you must handle the exception
        try
        {
            text = await ClipboardService.ReadTextAsync();
        }
        catch
        {
            Console.WriteLine("Cannot read from clipboard");
        }
    }

    async Task CopyToClipboard()
    {
        // Writing to the clipboard may be denied, so you must handle the exception
        try
        {
            await ClipboardService.WriteTextAsync("https://www.meziantou.net");
        }
        catch
        {
            Console.WriteLine("Cannot write text to clipboard");
        }
    }
}

Note that the first time, the user may need to allow access to the clipboard:

#Creating a nice Copy button

It's common to temporarily change the button text to "copied to clipboard" after clicking the button. This is pretty easy to do using Blazor:

@using System.Threading
@implements IDisposable
@inject ClipboardService ClipboardService

<button class="btn btn-primary" @onclick="CopyToClipboard" disabled=@state.IsDisabled>
    <i class="@state.IconClassName"></i> @state.Text
</button>

@code {
    CancellationTokenSource cts = new();
    State state = new("Copy", "oi oi-clipboard");

    async Task CopyToClipboard()
    {
        var temp = state;
        state = new("Copied", "oi oi-check", IsDisabled: true);
        await ClipboardService.WriteTextAsync("https://www.meziantou.net");
        await Task.Delay(TimeSpan.FromSeconds(2), cts.Token);
        state = temp;
    }

    public void Dispose()
    {
        cts.Cancel(); // Cancel Task.Delay
        cts.Dispose();
    }

    record State(string Text, string ClassName, bool IsDisabled = false);
}

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee