francojc
francojc

Reputation: 43

Creating hyperlinked text that returns the text clicked as input inside the app

I'm working with a Shiny project in which I would like to take text rendered inside the Shiny app and make each word in that text a hyperlink that when clicked sends the clicked text as an input to another function inside the app.

Here is a toy example of what I'm working with so far which only attempts to get the hyperlinked words to trigger an reactiveEvent and render the text that was clicked. Say my rendered text is in data. I markup the text in data and output the results as HTML to markup. Ideally what would happen is when I click the hyperlinked word 'This', the clicked_text output would display the text 'This'.

The actionLink syntax I'm using for the markup has two problems: 1) only the first hyperlinked word triggers input$clicked_text and 2) the value of input$clicked_text is an integer registering how many times the hyperlink as been clicked.

library(shiny)

ui <- fluidPage(
        htmlOutput("markup"),
        textOutput("clicked_text")
)

# sample data
data <- c("This", "is", "a", "sentence")

# function to markup text
markup.text <- function(data) {
        markup <- lapply(data, function(text) {
                paste0("<a id = 'clicked_text' href = '#' class = 'action-button shiny-bound-input' value = '",
                       text,
                       "'>",
                       text,
                       "</a>")
        }) %>%
                paste(collapse = " ")
        return(markup)
}

server <- function(input, output) {

        output$markup <- renderUI({ # display the marked-up text
                HTML(markup.text(data))
                })
        output$clicked_text <- eventReactive(input$clicked_text, { # display clicked text output
                input$clicked_text
        })
}

shinyApp(ui = ui, server = server)

Your help and suggestions are highly appreciated.

Upvotes: 1

Views: 1102

Answers (1)

MDe
MDe

Reputation: 2508

I think these revisions should do the trick:

  1. Change the link tag structure to look like this:

<a href='#' onclick='detect_click(this)'>text</a>

  1. Create a Javascript file in the same folder, called detect_click.js (could be named anything though). Put the following code in the file:

function detect_click(el) { Shiny.onInputChange('clicked_text', el.innerHTML); }

  1. Change the UI to read the Javascript file:

ui <- fluidPage( htmlOutput("markup"), textOutput("clicked_text"), includeScript("detect_click.js") )

  1. Now within the server, you can use input$clicked_text as if it were any ordinary Shiny input - create reactive objects and output as normal, and it'll change any time a link created with the tag structure above is clicked.

Upvotes: 3

Related Questions