Non-reactive DOM Manipulation

Logging changes in an input:


Reactive DOM Manipulation

Inserting an input object after some complicated JS calculation:

Making sure it worked (type in the box above and see your result here):


Modifying UI using JS
by Bárbara Borges

show with app
library(shiny)

function(input, output, session) {
  ## To make sure our JS-created textInput works:
  output$txt2Test <- renderText({ input$txt2 })
}
library(shiny)

fluidPage(
  ## link the JS file
  tags$head(tags$script(src="script.js")),
  ## link the CSS file
  tags$head(tags$link(rel="stylesheet", 
                      type="text/css",
                      href="style.css")),
  
  ## non-reactive DOM manipulation
  h4('Non-reactive DOM Manipulation'),
  p('Logging changes in an input:'),
  textInput('txt1', 'Enter some text'),
  tags$div(id = 'placeholder1'),
  hr(),
  
  ## reactive DOM manipulation
  h4('Reactive DOM Manipulation'),
  p(paste('Inserting an input object after some', 
          'complicated JS calculation:')),
  tags$div(id = 'placeholder2'),
  tags$em((paste('Making sure it worked (type', 
                 'in the box above and see', 
                 'your result here):'))),
  textOutput('txt2Test', inline = TRUE),
  br(), br(), br()
)
// Make sure the Shiny connection is established
$(document).on('shiny:connected', function(event) {

  /********** NON-REACTIVE DOM MANIPULATION **********/
  // Detect input change and change UI to reflect that
  var prevText = '';
  $(document).on('shiny:inputchanged', function(event) {
    if (event.name === 'txt1' && event.value !== prevText) {
      prevText = event.value;
      $('#placeholder1').append(
        'You have entered text: ' + event.value + '<br>'
      );
    }
  });
  
  /************ REACTIVE DOM MANIPULATION ************/
  // Insert a textInput after a complicated calculation
  function complicatedCalculation(a, b, callback) {
    var res = a + b;
    console.log('Complicated calculation finished!');
    callback(res);
  }
  
  complicatedCalculation(1, 1, function(value) {
    Shiny.unbindAll();
    // insert a reactive textInput
    $('#placeholder2').append(
      '<div class=\"form-group shiny-input-container\">' +
        '<label for=\"txt2\"> A JS-created textInput </label>' +
        '<input id=\"txt2\" type=\"text\"' +
                'class=\"form-control\" value=\"\">' + 
      '</div>'
    );
    $('#txt2').val(value);
    Shiny.bindAll();
  });
});
#placeholder1, #placeholder2 {
  min-height: 20px;
  padding: 19px;
  margin: 0px 15px;
  background-color: #f5f5f5;
  border: 1px solid #e3e3e3;
  border-radius: 4px;
  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
  box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
}

#showcase-app-code {
  padding: 50px;
  border: #ddd 8px solid;
}
Code license: MIT