Run js script from url using htmlOutput and renderText

Hi

I am trying to embed a weather widget in my shiny app, using js code sourced from a url. I have found various sources online for this and, whilst I can get some widgets to work, the one I want to use doesn't seem to work.

The ui.R and server.R are shown below. There are two widget options used here. The first one displays, but the second one is blank. Any ideas as to how I get it to display, please?

I can get the second one to work by putting it directly into html code (i.e. outside a shiny app) but cannot understand why it doesn't work in the shiny app.

Any help would be much appreciated.

Many Thanks

David.

#ui.R
library(shiny)
shinyUI(fluidPage(
  wellPanel(
    htmlOutput("widget1")
  ),
  wellPanel(
    htmlOutput("widget2")
  )
  )
  )
#server.R
library(shiny)
shinyServer(function(input, output) {
  output$widget1<-renderText({
    out1<-"<a class='weatherwidget-io' href='https://forecast7.com/en/51d51n0d13/london/' data-label_1='LONDON' data-label_2='WEATHER' data-theme='original' >LONDON WEATHER</a><script>"
    out2<-"!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src='https://weatherwidget.io/js/widget.min.js';fjs.parentNode.insertBefore(js,fjs);}}(document,'script','weatherwidget-io-js');</script>"
    out_all<-paste(out1,out2,"",sep="")
    out_all
  }  
  )
  output$widget2<-renderText({
    out4<-"<script type='text/javascript' src='https://darksky.net/widget/default/51.3055,-0.3072/us12/en.js?width=100%&height=350&title=ashtead, uk&textColor=333333&bgColor=FFFFFF&transparency=false&skyColor=333333&fontFamily=Default&customFont=&units=us&htColor=333333&ltColor=C7C7C7&displaySum=yes&displayHeader=yes'></script>"
    out4
  }  
  )
})

Does the second one work when the first isn't present? If not, you might consider removing the first one for the purposes of troubleshooting, as the more minimal the better! :slightly_smiling_face:

Good thought, but sadly, no, it still shows nothing.

OK! In that case, I'd recommend cutting the first widget for purposes of troubleshooting. I'm not sure why the second one isn't working. :slightly_frowning_face: Hopefully someone with more Shiny expertise than me (read: almost anyone) will be able to help!

I'm afraid I don't have a solution, but maybe a workaround? :confused: Do you need the widget to be reactive? It works non-reactively when included as tags output in the UI, e.g.:

ui <- fluidPage(
    
    # Does not work
    wellPanel(
        htmlOutput("darkSkyWidget")
    ),
    
    # Works
    wellPanel(
        tags$script(type='text/javascript', src='https://darksky.net/widget/default/51.3055,-0.3072/us12/en.js?width=100%&height=350&title=ashtead, uk&textColor=333333&bgColor=FFFFFF&transparency=false&skyColor=333333&fontFamily=Default&customFont=&units=us&htColor=333333&ltColor=C7C7C7&displaySum=yes&displayHeader=yes')
    )
)

server <- function(input, output) {
    
    output$darkSkyWidget <- renderText({
        "<script type='text/javascript' src='https://darksky.net/widget/default/51.3055,-0.3072/us12/en.js?width=100%&height=350&title=ashtead, uk&textColor=333333&bgColor=FFFFFF&transparency=false&skyColor=333333&fontFamily=Default&customFont=&units=us&htColor=333333&ltColor=C7C7C7&displaySum=yes&displayHeader=yes'></script>"
    })
    
}

shinyApp(ui = ui, server = server)

If you use the web inspector in your browser to examine the page, you can see that in the htmlOutput() version, the script doesn't seem to have been run (??). If you did want to make this widget respond reactively to shiny inputs, it seems like some different technique from htmlOutput() + renderText() is necessary, but I'm not sure I get why. Here's where I echo @mara in hoping that somebody who has a deeper understanding of how all the moving parts fit together will be able to help!

Thanks for this workaround, but, yes, I would ideally like it to respond to shiny user inputs. I

might try wrapping your version in an observeEvent to see if that works. As you say, someone else hopefully might know why the script doesn’t run with htmlOutput.

David.

Your suggestion certainly shows the weather widget, as required, but I want to control it on the server side. I tried wrapping your version in an ObserveEvent, and that didn't work. I also tried extendShinyjs, written by Dean Attali, but couldn't get that to work either. Code is below.

ui.R

library(shiny)
library(V8)
jsCode<-"shinyjs.weather1='src='https://darksky.net/widget/default/51.3055,-0.3072/us12/en.js?width=100%&height=350&title=ashtead, uk&textColor=333333&bgColor=FFFFFF&transparency=false&skyColor=333333&fontFamily=Default&customFont=&units=us&htColor=333333&ltColor=C7C7C7&displaySum=yes&displayHeader=yes''"
shinyUI(fluidPage(
  useShinyjs(),
    extendShinyjs(text=jsCode),
  actionButton("getforecast","Show forecast for selected location")
)  
  )

server.R

library(shiny)
shinyServer(function(input, output) {
  observeEvent(input$getforecast, {
        js$weather1()
  })
})

Must be doing something wrong. For example, I am not sure how to include the src functionality in the raw js code in ui.R as above. Any other suggestions gratefully received.

Thanks.