Skip to content

Instantly share code, notes, and snippets.

@timelyportfolio
Last active June 8, 2018 11:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timelyportfolio/c686384b058d1bc2f2149a5330da66c0 to your computer and use it in GitHub Desktop.
Save timelyportfolio/c686384b058d1bc2f2149a5330da66c0 to your computer and use it in GitHub Desktop.
React office-ui-fabric rating component used with R Shiny

As an extension to the blog post React in R, I thought it would be helpful to demonstrate how we can combine a React component with R Shiny.

screenshot of react working with R shiny

Code

library(htmltools)
library(shiny)
library(reactR)

fabric <- htmlDependency(
  name = "office-fabric-ui-react",
  version = "5.23.0",
  src = c(href="https://unpkg.com/office-ui-fabric-react/dist"),
  script = "office-ui-fabric-react.js",
  stylesheet = "css/fabric.min.css"
)

tl <- tagList(
  reactR::html_dependency_react(),
  fabric,
  tags$h3("React Rating from office-ui-fabric"),
  tags$div(id="react-rating"),
  tags$h3("Rating Communicated through Shiny"),
  textOutput("rtextrating"),
  tags$script(HTML(babel_transform(
"
    // office-ui-fabric rating example
    //   amended to work without Typescript
    //   https://developer.microsoft.com/en-us/fabric#/components/rating
    class RatingBasicExample extends React.Component {
      constructor(props) {
        super(props)
        
        this.state = {largeStarRating: null}

        this._onLargeStarChanged = this._onLargeStarChanged.bind(this)
      }

      _onLargeStarChanged(rating) {
        this.setState({largeStarRating: rating})

        // now communicate the change to Shiny
        if(Shiny && Shiny.onInputChange) {
          Shiny.onInputChange(
            'largeStarRating',
            rating
          )
        }
      }

      render() {
        return (
          <Fabric.Rating
            id={ 'largeRatingStar' }
            min={ 1 }
            max={ 5 }
            size={ Fabric.RatingSize.Large }
            rating={ this.state.largeStarRating }
            onChanged={ this._onLargeStarChanged }
          />
        )
      }
    }

    ReactDOM.render(
      <RatingBasicExample />,
      document.querySelector('#react-rating')
    )
"
  )))
)

ui <- tl

server <- function(input, output, session) {
  observeEvent(input$largeStarRating, {
    print(input$largeStarRating)
    output$rtextrating <- renderText(paste0(
      "React tells Shiny you rated me a ", input$largeStarRating
    ))
  })
}

shinyApp(ui, server, options=list("launch.browser"=TRUE))
@donarus
Copy link

donarus commented Apr 30, 2018

Hi, I'm little bit playing around shiny and react and I found your gist, which is very useful to me. But I'm trying to do little bit more and I'm not an expert with Shiny - I was able to make my react components interact with shiny using events (using onInputChange) and I'm able to send also messages from R to React components. But what I'm trying to do is to embed original shiny reactive components (for example textInputs or buttons) into react components:

...
<MyReactComponent attr1='...' attr2='...'>
   Here, I'd like to have embed some set of shiny components
</MyReactComponent>
...

For example for custom tablist I'd expect the following method structure but I don't know how to continue

tabList <- function(...) {
    tabs <- list(...)
    tabsIdx <- !nzchar(names(tabs) %OR% character(length(tabs)))
    attribs <- tabs[!tabsIdx]
    tabs <- tabs[tabsIdx]

   tags$script(HTML(paste0("
                       <Tabs>
                     # HERE I'D LIKE TO PASTE MY CHILD COMPONENTS (stored in 'tabs')
                       </Tabs>
   ")))
}

I don't have an idea how to do it, because we defined HTML directly using HTML.Any ideas how to do it nicely in shiny-like style?

library(shiny)
library(customComponents)

...
ui <- function() {
  tagList(
    customComponents::tabList(
      customComponents::tab(name='tab1', tags$div(..........)), 
      customComponents::tab(name='tab2', tags$div(..........)), 
      customComponents::tab(name='tab3', tags$div(..........))
    )
  )
}

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