Reading JavaScript Variable into Shiny/R on App Load

Reading javascript variable into shiny/R on app load

Erik Westlund was kind enough to provide the following solution.


get_user_id.js:

document.domain = "MYDOMAIN.com"; 

var userIDVariableName = parent.userID;
var userID = document.getElementById("userID");
userID.value = userIDVariableName;

var usernameVariableName = parent.username;
var username = document.getElementById("username");
username.value = usernameVariableName;

As mentioned above remember to change the domain. And set it in the page loading the iframe.


ui.R:

library(shiny) 

shinyUI( bootstrapPage(

# Hidden input boxes to save the variable to
HTML(‘ <input type="text" id="userID" name="userID" style="display: none;"> ‘),
HTML(‘ <input type="text" id="username" name="username" style="display: none;"> ‘),

# include the js code
includeScript("get_user_id.js"),

# Show the output
textOutput("view")
))

Change the path to the script as needed.


server.R:

shinyServer(function(input, output, session) { 

userID <- reactive({ input$userID })
username <- reactive({ input$username })

output$view <- renderText( paste0( "User ID is: ",userID()," and username is: ",username() ) )

})


Add this to the page containing the iframe:

PHP to get the variable from wordpress.

<?php global $current_user; 
get_currentuserinfo();
$user_name = $current_user->user_login;
$user_ID = get_current_user_id();
?>

And then this to make it a java variable:

<script type="text/javascript"> 
var username = <?php echo json_encode($user_name) ?> ;
var userID = <?php echo json_encode($user_ID) ?> ;
</script>

Set domain and the iframe:

<script type="text/javascript"> 
document.domain = "MYDOMAIN.com";
</script>
<iframe id="example1" style="border: none; width: 100%; height: 500px;" src="PATH_TO_SHINY_APP" width="300" height="150" frameborder="0"></iframe>

Access Javascript Variable in R Shiny Application

Theres wonderful function called Shiny.onInputChange it will do what you want

library(shiny)
library(shinyjs)
shinyApp(
ui = fluidPage(
useShinyjs(),
actionButton("btn", "Click me")
),
server = function(input, output) {
observeEvent(input$btn, {

runjs('var today_var = new Date(); alert(today_var);Shiny.onInputChange("today_var",today_var);')
print(input$today_var)

})
}
)

Receiving data from .js in server.R shiny

Regarding what NicE wrote:

In the file.js

var myVariable = //do something
Shiny.onInputChange("variableNameToWriteInServer.R", myVariable)

In the server.R

observe({
# thats how you access the variable
input$myVariable
#do something with the variable. To see if it worked something like
})

That should do the trick. If you use the getBounds() function keep that in mind Leaflet : Firing an event when bounds change. Also, you might not receive any output since the getBounds() function does not return the bounds of the window when the window extend is not changed. But, its only execute once. In the article I linked is a solution for this.

For further undocumented communication in Shiny (server.R and ui.R) read here: https://ryouready.wordpress.com/2013/11/20/sending-data-from-client-to-server-and-back-using-shiny/

Sending data from js to R Shiny variable

I believe you need to utilize the shiny:connected event. You are waiting for the document to be ready, but you also need to wait for shiny to be ready. The JavaScript Events in Shiny page touches on the related events and provides more details.

I put together a small example. The bare Shiny.onInputChange(..) complains that there is no Shiny object (see browser developer console) and input$missing is NULL. However, the Shiny.onInputChange(..) that waits on the shiny:connected event goes through and input$found is "[1,2,3,4,5]".

library(shiny)

on_ready <- paste(
"$(function() {",
"$(document).on('shiny:connected', function(e) {",
"Shiny.onInputChange('found', JSON.stringify([1, 2, 3, 4, 5]));",
"});",
"Shiny.onInputChange('missing', JSON.stringify(['where', 'am', 'I?']));",
"",
"});",
sep = "\n"
)

ui <- fluidPage(
tags$head(
tags$script(on_ready)
),
fluidRow(
column(
6,
h5("`input$missing`:"),
verbatimTextOutput("missingValue"),
p("(error, Shiny object is missing as connection is not yet established)")
),
column(
6,
h5("`input$found`:"),
verbatimTextOutput("foundValue"),
p("(no error, wait for `shiny:connected` event)")
)
)
)

server <- function(input, output) {
output$missingValue <- renderPrint({
input$missing
})

output$foundValue <- renderPrint({
input$found
})
}

shinyApp(ui, server)

How to modify a js variable within a shiny server (htmlwidgets/R)

This app assumes the global variable was assigned to the window. Then it uses a custom message handler to create the original variable (#1) and another to manipulate the value of that variable (#2).

Edited to have message sent back to R with the state of the global variable.

R Code:

library(shiny)

ui <- fluidPage(

# Application title
titlePanel("Global Variable Manipulation"),

mainPanel(
sliderInput("data", "Element", min = 0, max = 100, value = 0),
actionButton("go", "GO"),
textOutput("var"),
singleton(
tags$head(tags$script(src = "message-handler.js"))
),
singleton(
tags$head(tags$script(src = "message-handler2.js"))
),
singleton(
tags$head(tags$script(src = "back-to-shiny.js"))
)
)

)

server <- function(input, output, session) {

observe({
session$sendCustomMessage(type = 'testmessage',
message = list(a = 1, b = 'text',
controller = input$data))
})

observeEvent(input$go,{
session$sendCustomMessage(type = 'changeMessage',
message = list(2))
})

output$var <- renderPrint({
input$jsvalue
})
}

# Run the application
shinyApp(ui = ui, server = server)

message-handler.js code:

Shiny.addCustomMessageHandler("testmessage",
function(message) {
window.globalVar = message.controller
alert(JSON.stringify(window.globalVar));
}
);

message-handler2.js code:

Shiny.addCustomMessageHandler("changeMessage",
function(message) {
window.globalVar = window.globalVar-message;
alert(JSON.stringify(window.globalVar));
}
);

back-to-shiny.js code:

setInterval(function(){
var message = window.globalVar;
Shiny.onInputChange("jsvalue", message);
},0);

Creating a javascript variable from a custom message in shiny

Define insertion_text outside the message handler. In this way, it is a global variable.

And you can trigger a custom event on body when the message is sent:

<script> 
var insertion_text = null;
Shiny.addCustomMessageHandler("modified_text", function(message_from_r) {
alert(message_from_r);
insertion_text = message_from_r;
$("body").trigger("myCustomEvent");
});
$("body").on("myCustomEvent", function(){
document.getElementById("insertion_target").innerHTML = insertion_text;
})
</script>


Related Topics



Leave a reply



Submit