In this article, we are going to learn how we can Copy to Clipboard in a Blazor WebAssembly Project.

To download the source code for this article, you can visit our GitHub repository.

Let’s start.

How to Copy to Clipboard in Blazor WebAssembly?

When building applications, we may want to provide the ability to automatically copy data to a user’s clipboard on a button click, such as copying a code snippet or other useful information that would otherwise require the user to highlight and select copy.

Unfortunately, Blazor doesn’t directly provide the functionality for copying data to the clipboard. However, we can incorporate some JavaScript using the JSInterop.

When working in a browser, we get access to the JavaScript Clipboard API, which allows us to easily write data to the clipboard.

Now that we understand what we need to create for our Copy to Clipboard functionality, let’s start by creating a project.

Create Blazor WebAssembly Project

We start by creating a Blazor WebAssembly project by using the template provided by Visual Studio or using the dotnet new blazorwasm command.

We can go ahead and remove any of the boilerplate code generated, ensuring we leave Index.razor in the Pages folder, along with the components in the Shared folder.

Create a Clipboard Service

We are going to create a couple of components to demonstrate different scenarios, so let’s create a service that can be injected into our components and reused as needed.

Let’s start by creating IClipboardService

public interface IClipboardService
{
    Task CopyToClipboard(string text);
}

Next, we create an implementation for this interface:

public class ClipboardService : IClipboardService
{
    private readonly IJSRuntime _jsInterop;

    public ClipboardService(IJSRuntime jsInterop)
    {
        _jsInterop = jsInterop;
    }

    public async Task CopyToClipboard(string text)
    {
        await _jsInterop.InvokeVoidAsync("navigator.clipboard.writeText", text);
    }
}

First, we need to inject IJSRuntime. This allows us to interact with JavaScript in our C# code.

In CopyToClipboard() we call InvokeVoidAsync(), passing navigator.clipboard.writeText as our first parameter, which will call the JavaScript function.

Finally, we pass our text parameter as the text we want to write to the clipboard.

We also need to register this service as a scoped service in the Program class:

builder.Services.AddScoped<IClipboardService, ClipboardService>();

To learn more about dependency injection, check out our article about Dependency Injection in ASP.NET Core.

This covers the basic logic we need to copy data to the clipboard.

Create a Copy To Clipboard Component

We have a service that handles our Copy to Clipboard logic, so now we want to create a component that can be re-used in our application:

@inject IClipboardService ClipboardService

<button @onclick="OnClick" class="btn btn-primary">Copy to Clipboard</button>

@code {

    [Parameter]
    public string TextToCopy { get; set; }

    private async Task OnClick()
    {
        await ClipboardService.CopyToClipboard(TextToCopy);
    }
}

We start by injecting our IClipboardService.

Then we create a button element, adding an event handler for the onclick event. In our @code block, we create a TextToCopy parameter. We also add a class attribute, providing some Bootstrap classes.

Finally, we create an OnClick() method, that will call CopyToClipboard() and pass the TextToCopy parameter. 

Next, let’s create a component that we can use later to verify if our Copy to Clipboard logic is working correctly.

Create a Component to Show the Copied Text

We can verify that our Copy to Clipboard logic works as expected by simply creating a textarea to paste our data into:

<p>Paste text here: </p>
<textarea rows="10" cols="50"></textarea>

We create a simple paragraph to show the user what to do, along with a textarea element to allow users to paste data from their clipboard to verify the logic is working.

With this created, we can now look at some of the scenarios we could come across that would require the use of this component.

Single-line Copy to Clipboard

The first scenario in which we may wish to use our Copy to Clipboard component is when we have a single line of read-only text that the user would like to copy, such as a website or a repository URL.

Let’s create a component for this scenario:

@page "/singleline"

<h3>Singe-line Copy to Clipboard</h3>

<input type="text" readonly value="@text" />
<CopyToClipboard TextToCopy="@text" />

<TextArea />

@code {
    string text = "Some readonly text to copy";
}

Initially, we use the @page directive to mark this component as a routable component.

Then we create an input element, making sure to include the readonly attribute. We set the value to the text field that we define in our @code block.

Next, we include the CopyToClipboard component that we’ve created previously, passing the text field to the TextToCopy parameter.

Finally, we add the TextArea component defined previously to verify the Copy to Clipboard logic works as expected.

Multi-line Copy to Clipboard

Sometimes we may have a multi-line value that we would like to copy, such as a code snippet. We can use our CopyToClipboard component to provide this functionality:

@page "/multiline"

<h3>Multi-line Copy to Clipboard</h3>

<textarea readonly rows="3" cols="10">@text</textarea>
<CopyToClipboard TextToCopy="@text" />

<TextArea />

@code {
    string text = @"This is
a multiline 
code snippet";
}

Once again, we start by defining the route for this component.

This time, we create a textarea element, which allows for multi-line text input. Again, we use the readonly attribute. Within the textarea element, we place the text field defined in our @code block. This time we use the verbatim string to create a multiline text.

The final steps are the same as before. We add our CopyToClipboard component, passing in the text field to the TextToCopy parameter. Finally, we add the TextArea component.

Copy User Input

A final scenario where we can provide a Copy to Clipboard button would be when we ask the user for input in the form of an input or textarea element.

Let’s create a component for that:

@page "/userinput"

<h3>User input Copy to Clipboard</h3>

<input @bind-value="text" />
<CopyToClipboard TextToCopy="@text" />

<TextArea />

@code {
    string text = "";
}

We start by creating this component routable with the @page directive.

Then, we define an input element, using the @bind-value attribute to bind to the text field we create in the @code block.

Finally, we add the CopyToClipboard and TextArea components.

Define the Navigation Links

Before we test the Copy to Clipboard functionality, let’s add our routable components to the NavMenu component:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="singleline">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Single-line
    </NavLink>
</div>
<div class="nav-item px-3">
    <NavLink class="nav-link" href="multiline">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Multi-line
    </NavLink>
</div>
<div class="nav-item px-3">
    <NavLink class="nav-link" href="userinput">
        <span class="oi oi-list-rich" aria-hidden="true"></span> User Input
    </NavLink>
</div>

We add 3 NavLinks to the existing NavMenu, ensuring to set the href for each of the components we created.

Test Copy to Clipboard Functionality

We have everything we need to test our functionality, so let’s run our application and navigate to /singleline first and then click our Copy to Clipboard button:

Single Line Copy to Clipboard

Placing our cursor in the textarea, we can verify our Copy to Clipboard functionality works by pressing Ctrl + V or right-clicking and selecting Paste:

Single Line Copy to Clipboard Result

Next, we’ll test a multi-line textarea, by navigating to /multiline and running the same test: 

Multi-Line Copy to Clipboard

Once again, we can verify that our functionality works as expected:

Multi-Line Copy to Clipboard Result

Style the Copy to Clipboard Component

So far, the user has no way of confirming if the data has been copied to their clipboard, without attempting to paste it. So let’s provide some visual feedback to let the user know the data has been successfully copied to their clipboard.

Let’s revisit our CopyToClipboard component and add some extra logic: 

@inject IClipboardService ClipboardService

<button @onclick="OnClick" class="@buttonClass">@buttonText</button>

@code {
    [Parameter]
    public string TextToCopy { get; set; }

    private const string _copyToClipboardText = "Copy to clipboard";
    private const string _copiedToClipboardText = "Copied to clipboard";

    private const string _defaultClass = "btn btn-primary";
    private const string _successClass = "btn btn-success";

    private string buttonText = _copyToClipboardText;
    private string buttonClass = _defaultClass;

    private async Task OnClick()
    {
        await ClipboardService.CopyToClipboard(TextToCopy);

        buttonText = _copiedToClipboardText;
        buttonClass = _successClass;

        StateHasChanged();
        await Task.Delay(TimeSpan.FromSeconds(2));

        buttonText = _copyToClipboardText;
        buttonClass = _defaultClass;
    }
}

First, we change the class attribute to our button element, binding it to the buttonClass field we define in the @code block. Also, we set the button text to the buttonText field.

Then, we define some string constants, for the different states we want to set the button class and text in. We must remember to set the initial state of our button text and class to the _copyToClipboardText and _defaultClass fields. 

This time, in the OnClick() method, once the text has been copied to the clipboard, we set buttonText to _copiedToClipboard field, and buttonClass to _successClass. We need to remember to call the StateHasChanged method to re-render our button.

Finally, We put in a 2-second delay and reset our button to the normal state.

Let’s run the application and navigate to /userinput to see our changes in action:

User Input Copy to Clipboard

This time around, when we click the button, the text and color change as we specified. After 2 seconds, the text and color will revert to the original ones. We can also confirm our user input component works as expected:

User Input Copy to Clipboard Result

Conclusion

Now we know how to implement Copy to Clipboard in Blazor WebAssembly applications. This feature is very useful for complex or very long areas of data, such as URLs or code snippets, where we want to provide the user with an easy way to copy this data to their clipboard.