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
Creating a "Sticky" Fixed-Position Item That Works on iOS Safari
How to Find All Subsets of a Set in JavaScript? (Powerset of Array)
How to Write Asynchronous Functions for Node.Js
Merge Keys Array and Values Array into an Object in JavaScript
Safari on iOS 9 Does Not Trigger Click Event on Hidden Input File
How to Implement Jquery.Noconflict()
How to Execute Array of Promises in Sequential Order
Alternative to Jquery's .Toggle() Method That Supports Eventdata
What Is an Exclamation Point in JavaScript
How to Use a Numeric Type as an Object Key
How to Detect Faces Using Ruby
Access Parent's Parent from JavaScript Object
How Should Look a Application.Scss File in Ruby
Wait for Multiple Promises to Finish
How to Reference Other Properties During Object Declaration in JavaScript
How to Make a Shared State Between Two React Components
Firebase Cloud Function Won't Store Cookie Named Other Than "_Session"