Search code examples
rshinyplotlyr-plotly

How to implement and display sentences with clickable words in R Shiny application?


I design a shiny application which one of its features is to generate new sentences (via Markov strings) from a base corpus. Let's say I generated 10 sentences, of moderate length.

sentences <— c(rep(c("This is a test sentence of moderate length", "This is another test sentence of moderate length"),5))

I would like to be able to display these sentences, one per line, quite distinctly, in my Shiny application, allowing a little interactivity. In particular, I would like the words to be clickable on a plotly_click model (cf plotly package) in order to use the clicked word as input for other manipulations.

Ideally, in an additional but secondary way, I would even like the words to be manually replaceable by the user.

I have looked into the different shiny components (shiny base, htmlwidgets, plotly etc.) without finding satisfactory solutions so far and I rely on your ideas and proposals,

Thanks a lot


Solution

  • This is one possible way of implementing an app just using base Shiny functions where a number of sentences are displayed, and clicking each individual word creates a new input containing just that word, which can then be used in other calculations or processes.

    What I've done is manually create a load of HTML hyperlink tags wrapped around each individual word, and used the Shiny.setInputValue Javascript function to create a new Shiny input callable with input$word whenever a user clicks on a given word. To prove that a new input has been created that can be used elsewhere, I've just printed it out below the main list using renderText - you'll see that whenever you click on a different word, the textOutput updates to print the clicked word:

    library(shiny)
    
    ui <- fluidPage(
        uiOutput("sentences"),
        br(),br(),
        textOutput("word")
    )
    
    server <- function(input, output) {
    
        sentences <- c(rep(c("This is a test sentence of moderate length", "This is another test sentence of moderate length"),5))
        
        output$sentences <- renderUI({
            link_sentences <- lapply(sentences, function(x) {
                words <- unlist(strsplit(x, " ", fixed = TRUE))
                sentence <- paste0("<a href='#' onclick='Shiny.setInputValue(\"word\", \"", words, "\");'>",
                                  words,
                                  "</a>",
                                  collapse = "",
                                  sep = " ")
                HTML(paste("<br>", sentence, "</br>"))
            })
            do.call(tagList, link_sentences)
        })
        
        output$word <- renderText(input$word)
    }
    
    shinyApp(ui = ui, server = server)