Skip to content

Instantly share code, notes, and snippets.

@xiaodaigh
Last active February 2, 2016 18:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save xiaodaigh/7150112 to your computer and use it in GitHub Desktop.
Save xiaodaigh/7150112 to your computer and use it in GitHub Desktop.
R Shiny: An textInput that only gets invalidated upon losing focus or when enter is pressed shiny::runGist("7150112")
library(shiny)
shinyServer(function(input, output, session) {
# Partial example
output$meh <- renderPrint({
print("Press enter or focusout to update --- ")
print(input$myTextInput )
})
})
library(shiny)
myTextInput <- function(inputId, label, value = "") {
#singleton(tags$head(tags$script(src = "/temp/mytextinput.js"))),
tagList(tags$label(label, `for` = inputId), tags$input(id = inputId,
type = "text", value = value,class="myTextInput"))
}
code = HTML(" <script> var myTextInputBinding = new Shiny.InputBinding();
$.extend(myTextInputBinding, {
find: function(scope) {
return $(scope).find('.myTextInput');
},
getId: function(el) {
//return InputBinding.prototype.getId.call(this, el) || el.name;
return $(el).attr('id')
},
getValue: function(el) {
return el.value;
},
setValue: function(el, value) {
el.value = value;
},
subscribe: function(el, callback) {
$(el).on('keyup.textInputBinding input.textInputBinding', function(event) {
if(event.keyCode == 13) { //if enter
callback()
}
});
$(el).on('focusout.myTextInputBinding', function(event) { // on losing focus
callback();
});
},
unsubscribe: function(el) {
$(el).off('.myTextInputBinding');
},
receiveMessage: function(el, data) {
if (data.hasOwnProperty('value'))
this.setValue(el, data.value);
if (data.hasOwnProperty('label'))
$(el).parent().find('label[for=' + el.id + ']').text(data.label);
$(el).trigger('change');
},
getState: function(el) {
return {
label: $(el).parent().find('label[for=' + el.id + ']').text(),
value: el.value
};
},
getRatePolicy: function() {
return {
policy: 'debounce',
delay: 250
};
}
});
Shiny.inputBindings.register(myTextInputBinding, 'shiny.myTextInput');</script>")
shinyUI(
basicPage(
code
,myTextInput("myTextInput","My text input","On enter or focus out")
,textOutput("meh")
,HTML('<script src="https://gist.github.com/xiaodaigh/7150112.js"></script>')
))
@homerhanumat
Copy link

This is very useful. Thanks!

One small suggestion: in order to make the styling the same as regular shiny::textInput(), modify your function definition to:

myTextInput <- function(inputId, label, value = "") {
    tagList(tags$label(label, `for` = inputId), 
            tags$input(id = inputId, 
                      type = "text", value = value,
                      class="myTextInput form-control shiny-bound-input"))

@homerhanumat
Copy link

How silly of me. Apparently you intended to change the styling.

@homerhanumat
Copy link

After further study I realized that the class attribute needs to be as per my original suggestion. Again, thank you for posting this gist: it was just what I needed in order to begin to understad the construction of customized inputs. I studied the matter in more details and made a package that permits the author of a Shiny app to create several customized input controls with just a single R command: https://github.com/homerhanumat/shinyCustom.

@esmeraldaw
Copy link

Thanks for your package. I found it very useful. Just one question remains: how do I make ENTER act like TAB, i.e. when user presses ENTER, the customTextInput should lose focus and the next element receives focus, just as if TAB were pressed? Thanks in advance for your answer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment