Yifu Yan
Yifu Yan

Reputation: 6106

How to Define CSS for Elements inside Shiny Modules

I'm trying to achieve the following result in HTML using shiny Module:

Outside shiny module: p tag is black, when hover mouse over the it, cursor should be changed to pointer and color should be changed grey.

Inside shiny module: p tag is blue, when hover mouse over it, cursor should be changed to pointer and color should be changed to red.

The HTML version works: demo

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
    <style>
        p{color:black;}
        p:hover{color:grey;cursor:pointer;}

        #mymodule p{color:blue;}
        #mymodule p:hover{color:red;cursor:pointer;}

    </style>
</head>
<body>
    <p>text outside module</p>
    <div id='mymodule'>
        <p>text inside module</p>
    </div>
</body>
</html>
    <p>some text</p>
</body>
</html>

I tried to add CSS for the module, but it seems like it doesn't work. What should I do? Any help is appreciated, thanks!

library(shiny)
library(glue)
library(shinyjs)

mymoduleUI <- function(id){
    ns <- NS(id)
    uiOutput(ns("text"))
}

mymodule <- function(input,output,session,color,colorHover){
    id <- session$ns("mymoduleUI")
    css_text <- glue("#{id} p{{color:{color};}}
                    #{id} p:hover{{color:{colorHover};}}")
    print(css_text)
    output$text <- renderUI({
        shinyjs::inlineCSS(rules = css_text)
        tags$p("text inside module")
    })
}


shinyApp(
    ui = basicPage(
        tags$head(tags$style("p{color:balck;}
                             p:hover{color:grey}")),
        tags$p("text outside module"),
        mymoduleUI("here")
    ),
    server = function(input, output) {
        callModule(module = mymodule,id = 'here',color="blue",colorHover="red")
    }
)



Upvotes: 1

Views: 1969

Answers (1)

GyD
GyD

Reputation: 4072

There were the following errors:

  1. As pointed out by r2evans, useShinyjs() statement was missing
  2. Use session$ns("text") instead of session$ns("mymoduleUI"). The id of the uiOutput is 'here-text', but the original version returns 'here-mymoduleUI'.
  3. If you set the css about the same time as you create the element it won't apply, as the element doesn't even exist by then.

If there can be numerous instances of this module each with different css I would recommend attaching css rules to the head as seen below. Otherwise if there were only a certain amount of options (e.g.: color: red, blue, green), then I would create css classes beforehand, and use class = ....

Code:

mymodule <- function(input,output,session,color,colorHover){
  id <- session$ns("text")

  css_text <- glue("
    $('head').append('<style type=\"text/css\">#{id} p{{color:{color}}} #{id} p:hover{{ color:{colorHover}}}</style>');
  ")
  print(css_text)
  output$text <- renderUI({
    tags$p("text inside module")
  })

  observe( {
    shinyjs::runjs(css_text)
  })
}

Output:

Output

Upvotes: 2

Related Questions