DCC.Clipboard.clipboard

The DCC.Clipboard.clipboard component copies text to the
user’s clipboard with a single click.

Examples

Find a few usage examples below.

Simple Clipboard Example

The easiest way to trigger the copy is by using the targetId property.
No callback is required! Place DCC.Clipboard.clipboard in the layout where
you would like the copy icon located. Specify the Clipboard.Attr.targetId of the component
with text to copy. In this example, the content of the value property of the
DCC.Textarea.textarea is copied to the clipboard.

open Giraffe
open Dash.NET
open Dash.NET.DCC
open Dash.NET.Giraffe
open Microsoft.Extensions.Logging

let layout =
    Html.div [
        Attr.children [
            Textarea.textarea "textarea_id" [
                Textarea.Attr.value "Copy and paste here"
                Textarea.Attr.style [
                    StyleProperty ("height", 100)
                ]
            ]
            Clipboard.clipboard "clipboard" [
                Clipboard.Attr.targetId "textarea_id"
                Clipboard.Attr.title "copy"
                Clipboard.Attr.style [
                    StyleProperty ("display", "inline-block")
                    StyleProperty ("fontSize", 20)
                    StyleProperty ("verticalAlign", "top")
                ]
            ]
        ]
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Clipboard Icon inside a Scrollable Div

The style and className can be used to change the design or the position
of the copy icon. This example shows the icon placed in the top right corner
of a scrollable div.

open Dash.NET
open Dash.NET.DCC
open Dash.NET.Giraffe

let code = """```python
html.Div([
    dcc.Markdown(
        code,
        id="code",
        style={"width": 500, "height": 200, "overflow": "auto"},
    ),
    dcc.Clipboard(
        target_id="code",
        style={
            "position": "absolute",
            "top": 0,
            "right": 20,
            "fontSize": 20,
        },
    ),
], style={"width": 500, "height": 200, "position": "relative"})
```"""
let layout =
    Html.div [
        Attr.children [
            Markdown.markdown "code" [
                Markdown.Attr.children code
                Markdown.Attr.style [
                    StyleProperty ("width", 500)
                    StyleProperty ("height", 200)
                    StyleProperty ("overflow", "auto")
                ]
            ]
            Clipboard.clipboard "clipboard" [
                Clipboard.Attr.targetId "code"
                Clipboard.Attr.style [
                    StyleProperty ("position", "absolute")
                    StyleProperty ("top", 0)
                    StyleProperty ("right", 20)
                    StyleProperty ("fontSize", 20)
                ]
            ]
        ]
        Attr.style [
            StyleProperty ("width", 500)
            StyleProperty ("height", 200)
            StyleProperty ("position", "relative")
        ]
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Cras non lacus maximus,
tincidunt nibh in, finibus nisi. Cras
ut lacus sed lacus tempus rutrum. Integer
ut feugiat nisi, nec tempus velit.

Proin placerat erat odio, et laoreet
sapien mattis et. Curabitur laoreet imperdiet
congue. Integer congue a augue non vulputate.
Ut a leo auctor, sodales sem ac, cursus
ipsum. Fusce in est nec urna pretium
aliquet. Nunc nisl eros, blandit eu diam
convallis, elementum dictum tortor.

Updating the Clipboard Text in a Callback

When targetId is not specified, the content of the text property
is copied to the clipboard. This works well with components like the DataTable
where you may want to customize the text in a callback. In this example,
the data is converted to FSharp.Data.CsvFile and converted to text using SaveToString(). See the
FSharp.Data CSV Parser documentation
on using the parser.

open Plotly.NET
open Dash.NET
open Dash.NET.DCC
open Dash.NET.Giraffe
open Dash.NET.DashTable
open FSharp.Data

let csv =
    CsvFile
        .Load("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")
        .Cache()

module CsvFile =
    let toSameColumnOrder : (string * obj) [] -> (string * obj) [] =
        Array.sortBy (
            fst
            >> fun columnName ->
                csv.Headers
                |> Option.map (Array.findIndex ((=) columnName))
        )

    let parse (data : seq<(string * obj) []>) =
        let c =
            CsvFile.Parse(
                data
                |> Seq.head
                |> Seq.map fst
                |> fun colunns -> System.String.Join(',', colunns)
            )
        data
        |> Seq.map (fun cs -> CsvRow(c, cs |> Array.map (snd >> string)))
        |> c.Append

let layout =
    Html.div [
        Attr.children [
            Clipboard.clipboard "datatable_copy" [
                Clipboard.Attr.style [
                    StyleProperty ("fontSize", 18)
                    StyleProperty ("color", "white")
                    StyleProperty ("backgroundColor", "grey")
                    StyleProperty ("height", 38)
                ]
            ]
            RadioItems.radioItems "copy_selected" [
                RadioItems.Attr.options [
                    RadioItemsOption.init("Copy All", "all")
                    RadioItemsOption.init("Copy Selected", "some")
                ]
                RadioItems.Attr.value "all"
                RadioItems.Attr.style [ StyleProperty ("display", "inline-block") ]
            ]
            DataTable.dataTable "datatable" [
                DataTable.Attr.startCell (DataTable.Cell.init(0L))
                DataTable.Attr.endCell (DataTable.Cell.init(0L))
                DataTable.Attr.derivedVirtualData Seq.empty
                DataTable.Attr.columns (
                    csv.Headers
                    |> Option.map (Array.map (fun h -> DataTable.Column.init(h, h)))
                    |> Option.defaultValue Array.empty
                )
                DataTable.Attr.data (
                    csv.Headers
                    |> Option.map (fun hs ->
                        csv.Rows
                        |> Seq.map (fun r ->
                            [ for i in 0..csv.NumberOfColumns - 1 -> hs.[i], box r.[i] ]
                            |> Map.ofList
                        )
                    )
                    |> Option.defaultValue Seq.empty
                )
            ]
        ]
    ]

let customCopyCallback =
    let outputTarget = "datatable_copy" @. CustomProperty "content"
    Callback.singleOut (
        "datatable_copy" @. N_Clicks,
        outputTarget,
        (fun (_: int) (startCell: DataTable.Cell) (endCell: DataTable.Cell) (data: seq&lt;Map<string,&gt;>) (copySelected: string) ->
            let copyData =
                data
                |> Seq.map (Map.toArray >> CsvFile.toSameColumnOrder)
                |> (match copySelected with
                    | "some" ->
                        Array.ofSeq
                        >> fun rows -> rows.[int (startCell?row :?> int64)..int (endCell?row :?> int64)]
                        >> Array.map (fun columns -> columns.[int (startCell?column :?> int64)..int (endCell?column :?> int64)])
                        >> Array.toSeq
                    | _ -> id
                    >> CsvFile.parse)
            outputTarget => (copyData.SaveToString())
        ),
        State = [
            CallbackState.create("datatable", "start_cell")
            CallbackState.create("datatable", "end_cell")
            CallbackState.create("datatable", "derived_virtual_data")
            CallbackState.create("copy_selected", "value")
        ]
    )

[&lt;EntryPoint&gt;]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.addCallback customCopyCallback
    |> DashApp.run [||] (DashGiraffeConfig.initDefault "localhost")

Limitations

This component uses theClipboard API. This feature is available only in secure contexts
(HTTPS), in some or all supporting browsers. When
the Clipboard API is unavailable, the icon will not appear in the app and a warning message is
written to the console.

Currently DCC.Clipboard.clipboard only supports copying text to the
clipboard. It does not support paste or other clipboard operations.


Clipboard Properties

Our recommended IDE for writing Dash apps is Dash Enterprise’s
Data Science Workspaces,
which has typeahead support for Dash Component Properties.
Find out if your company is using
Dash Enterprise
.

id (string; optional):
The ID used to identify this component.

target_id (string | record; optional):
The id of target component containing text to copy to the clipboard.
The inner text of the children prop will be copied to the clipboard.
If none, then the text from the value prop will be copied.

content (string; optional):
The text to be copied to the clipboard if the target_id is None.

n_clicks (number; default 0):
The number of times copy button was clicked.

html_content (string; optional):
The clipboard html text be copied to the clipboard if the target_id
is None.

title (string; optional):
The text shown as a tooltip when hovering over the copy icon.

style (record; optional):
The icon’s styles.

className (string; optional):
The class name of the icon element.

loading_state (record; optional):
Object that holds the loading state object coming from dash-renderer.

loading_state is a record with keys:

  • component_name (string; optional):
    Holds the name of the component that is loading.

  • is_loading (bool; optional):
    Determines if the component is loading or not.

  • prop_name (string; optional):
    Holds which property is loading.