gui/docs/ref/wails-v3/features/clipboard/basics.mdx
Snider 4bdbb68f46
Some checks failed
Security Scan / security (push) Failing after 9s
Test / test (push) Failing after 1m21s
refactor: update import path from go-config to core/config
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-14 10:26:36 +00:00

493 lines
9.9 KiB
Text

---
title: Clipboard Operations
description: Copy and paste text with the system clipboard
sidebar:
order: 1
---
import { Card, CardGrid } from "@astrojs/starlight/components";
## Clipboard Operations
Wails provides a **unified clipboard API** that works across all platforms. Copy and paste text with simple, consistent methods on Windows, macOS, and Linux.
## Quick Start
```go
// Copy text to clipboard
app.Clipboard.SetText("Hello, World!")
// Get text from clipboard
text, ok := app.Clipboard.Text()
if ok {
fmt.Println("Clipboard:", text)
}
```
**That's it!** Cross-platform clipboard access.
## Copying Text
### Basic Copy
```go
success := app.Clipboard.SetText("Text to copy")
if !success {
app.Logger.Error("Failed to copy to clipboard")
}
```
**Returns:** `bool` - `true` if successful, `false` otherwise
### Copy from Service
```go
type ClipboardService struct {
app *application.Application
}
func (c *ClipboardService) CopyToClipboard(text string) bool {
return c.app.Clipboard.SetText(text)
}
```
**Call from JavaScript:**
```javascript
import { CopyToClipboard } from './bindings/myapp/clipboardservice'
await CopyToClipboard("Text to copy")
```
### Copy with Feedback
```go
func copyWithFeedback(text string) {
if app.Clipboard.SetText(text) {
app.Dialog.Info().
SetTitle("Copied").
SetMessage("Text copied to clipboard!").
Show()
} else {
app.Dialog.Error().
SetTitle("Copy Failed").
SetMessage("Failed to copy to clipboard.").
Show()
}
}
```
## Pasting Text
### Basic Paste
```go
text, ok := app.Clipboard.Text()
if !ok {
app.Logger.Error("Failed to read clipboard")
return
}
fmt.Println("Clipboard text:", text)
```
**Returns:** `(string, bool)` - Text and success flag
### Paste from Service
```go
func (c *ClipboardService) PasteFromClipboard() string {
text, ok := c.app.Clipboard.Text()
if !ok {
return ""
}
return text
}
```
**Call from JavaScript:**
```javascript
import { PasteFromClipboard } from './bindings/myapp/clipboardservice'
const text = await PasteFromClipboard()
console.log("Pasted:", text)
```
### Paste with Validation
```go
func pasteText() (string, error) {
text, ok := app.Clipboard.Text()
if !ok {
return "", errors.New("clipboard empty or unavailable")
}
// Validate
if len(text) == 0 {
return "", errors.New("clipboard is empty")
}
if len(text) > 10000 {
return "", errors.New("clipboard text too large")
}
return text, nil
}
```
## Complete Examples
### Copy Button
**Go:**
```go
type TextService struct {
app *application.Application
}
func (t *TextService) CopyText(text string) error {
if !t.app.Clipboard.SetText(text) {
return errors.New("failed to copy")
}
return nil
}
```
**JavaScript:**
```javascript
import { CopyText } from './bindings/myapp/textservice'
async function copyToClipboard(text) {
try {
await CopyText(text)
showNotification("Copied to clipboard!")
} catch (error) {
showError("Failed to copy: " + error)
}
}
// Usage
document.getElementById('copy-btn').addEventListener('click', () => {
const text = document.getElementById('text').value
copyToClipboard(text)
})
```
### Paste and Process
**Go:**
```go
type DataService struct {
app *application.Application
}
func (d *DataService) PasteAndProcess() (string, error) {
// Get clipboard text
text, ok := d.app.Clipboard.Text()
if !ok {
return "", errors.New("clipboard unavailable")
}
// Process text
processed := strings.TrimSpace(text)
processed = strings.ToUpper(processed)
return processed, nil
}
```
**JavaScript:**
```javascript
import { PasteAndProcess } from './bindings/myapp/dataservice'
async function pasteAndProcess() {
try {
const result = await PasteAndProcess()
document.getElementById('output').value = result
} catch (error) {
showError("Failed to paste: " + error)
}
}
```
### Copy Multiple Formats
```go
type CopyService struct {
app *application.Application
}
func (c *CopyService) CopyAsPlainText(text string) bool {
return c.app.Clipboard.SetText(text)
}
func (c *CopyService) CopyAsJSON(data interface{}) bool {
jsonBytes, err := json.MarshalIndent(data, "", " ")
if err != nil {
return false
}
return c.app.Clipboard.SetText(string(jsonBytes))
}
func (c *CopyService) CopyAsCSV(rows [][]string) bool {
var buf bytes.Buffer
writer := csv.NewWriter(&buf)
for _, row := range rows {
if err := writer.Write(row); err != nil {
return false
}
}
writer.Flush()
return c.app.Clipboard.SetText(buf.String())
}
```
### Clipboard Monitor
```go
type ClipboardMonitor struct {
app *application.Application
lastText string
ticker *time.Ticker
stopChan chan bool
}
func NewClipboardMonitor(app *application.Application) *ClipboardMonitor {
return &ClipboardMonitor{
app: app,
stopChan: make(chan bool),
}
}
func (cm *ClipboardMonitor) Start() {
cm.ticker = time.NewTicker(1 * time.Second)
go func() {
for {
select {
case <-cm.ticker.C:
cm.checkClipboard()
case <-cm.stopChan:
return
}
}
}()
}
func (cm *ClipboardMonitor) Stop() {
if cm.ticker != nil {
cm.ticker.Stop()
}
cm.stopChan <- true
}
func (cm *ClipboardMonitor) checkClipboard() {
text, ok := cm.app.Clipboard.Text()
if !ok {
return
}
if text != cm.lastText {
cm.lastText = text
cm.app.Event.Emit("clipboard-changed", text)
}
}
```
### Copy with History
```go
type ClipboardHistory struct {
app *application.Application
history []string
maxSize int
}
func NewClipboardHistory(app *application.Application) *ClipboardHistory {
return &ClipboardHistory{
app: app,
history: make([]string, 0),
maxSize: 10,
}
}
func (ch *ClipboardHistory) Copy(text string) bool {
if !ch.app.Clipboard.SetText(text) {
return false
}
// Add to history
ch.history = append([]string{text}, ch.history...)
// Limit size
if len(ch.history) > ch.maxSize {
ch.history = ch.history[:ch.maxSize]
}
return true
}
func (ch *ClipboardHistory) GetHistory() []string {
return ch.history
}
func (ch *ClipboardHistory) RestoreFromHistory(index int) bool {
if index < 0 || index >= len(ch.history) {
return false
}
return ch.app.Clipboard.SetText(ch.history[index])
}
```
## Frontend Integration
### Using Browser Clipboard API
For simple text, you can use the browser's clipboard API:
```javascript
// Copy
async function copyText(text) {
try {
await navigator.clipboard.writeText(text)
console.log("Copied!")
} catch (error) {
console.error("Copy failed:", error)
}
}
// Paste
async function pasteText() {
try {
const text = await navigator.clipboard.readText()
return text
} catch (error) {
console.error("Paste failed:", error)
return ""
}
}
```
**Note:** Browser clipboard API requires HTTPS or localhost, and user permission.
### Using Wails Clipboard
For system-wide clipboard access:
```javascript
import { CopyToClipboard, PasteFromClipboard } from './bindings/myapp/clipboardservice'
// Copy
async function copy(text) {
const success = await CopyToClipboard(text)
if (success) {
console.log("Copied!")
}
}
// Paste
async function paste() {
const text = await PasteFromClipboard()
return text
}
```
## Best Practices
### ✅ Do
- **Check return values** - Handle failures gracefully
- **Provide feedback** - Let users know copy succeeded
- **Validate pasted text** - Check format and size
- **Use appropriate method** - Browser API vs Wails API
- **Handle empty clipboard** - Check before using
- **Trim whitespace** - Clean pasted text
### ❌ Don't
- **Don't ignore failures** - Always check success
- **Don't copy sensitive data** - Clipboard is shared
- **Don't assume format** - Validate pasted data
- **Don't poll too frequently** - If monitoring clipboard
- **Don't copy large data** - Use files instead
- **Don't forget security** - Sanitise pasted content
## Platform Differences
### macOS
- Uses NSPasteboard
- Supports rich text (future)
- System-wide clipboard
- Clipboard history (system feature)
### Windows
- Uses Windows Clipboard API
- Supports multiple formats (future)
- System-wide clipboard
- Clipboard history (Windows 10+)
### Linux
- Uses X11/Wayland clipboard
- Primary and clipboard selections
- Varies by desktop environment
- May require clipboard manager
## Limitations
### Current Version
- **Text only** - Images not yet supported
- **No format detection** - Plain text only
- **No clipboard events** - Must poll for changes
- **No clipboard history** - Implement yourself
### Future Features
- Image support
- Rich text support
- Multiple formats
- Clipboard change events
- Clipboard history API
## Next Steps
<CardGrid>
<Card title="Bindings" icon="rocket">
Call Go functions from JavaScript.
[Learn More →](/features/bindings/methods)
</Card>
<Card title="Events" icon="star">
Use events for clipboard notifications.
[Learn More →](/features/events/system)
</Card>
<Card title="dialogs" icon="information">
Show copy/paste feedback.
[Learn More →](/features/dialogs/message)
</Card>
<Card title="Services" icon="puzzle">
Organise clipboard code.
[Learn More →](/features/bindings/services)
</Card>
</CardGrid>
---
**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [clipboard examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples).