- {name}
{names.map((name) =>
)}
An open API service indexing awesome lists of open source software.
Single-File Components powered app
https://github.com/rinterface/shinycomponent
ecma golem-apps shiny-apps template-co webpack
Last synced: 2 months ago
JSON representation
Single-File Components powered app
---
output: github_document
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```# shinyComponent
[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)
[![R-CMD-check](https://github.com/RinteRface/shinyComponent/workflows/R-CMD-check/badge.svg)](https://github.com/RinteRface/shinyComponent/actions)App powered by {golem}, webpack, Framework7 components (esm). WIP
App is deployed on [shinyapps.io](https://dgranjon.shinyapps.io/shinyComponent/).## Installation
You can install the released version of shinyComponent from [CRAN](https://CRAN.R-project.org) with:
``` r
remotes::install_github("RinteRface/shinyComponent")
```## Proof of Concept
Interface is built with Framework 7 from JS, powered by webpack. We leverage
Template components to create the app root and subroutes. On the server side, we process data from R and send them back to JS to update the components.### UI
Components may be written with JSX (supported by the framework7-loader, no need to install `React`!), which is more convenient than the classic template syntax. Components have either the old/new syntax so you can compare both approaches.### Main page
App component is driven by:```jsx
import ListItem from './custom-list.f7.jsx';export default (props, {$f7, $f7ready, $on, $update }) => {
const title = 'Hello World';
let names = ['John', 'Vladimir', 'Timo'];Shiny.addCustomMessageHandler('init', function(message) {
names = message;
$update();
});// App events callback
$on('click', () => {
// callback
});// This method need to be used only when you use Main App Component
// to make sure to call Framework7 APIs when app initialized.
$f7ready(() => {
// do stuff
console.log('Hello');
});const openAlert = () => {
$f7.dialog.alert(title, function() {
// ok button callback
Shiny.setInputValue('alert_opened', false);
});
Shiny.setInputValue('alert_opened', true);
Shiny.setInputValue(
'alert',
{
message: 'Alert dialog was triggered!',
title: title,
},
{priority: 'event'}
);
}const openPanel = () => {
$f7.panel.open('.panel-left');
}return () => (
"Hello"
{names.map((name) =>
- {name}
)}
)
}
```Below is the code a of local sub-component, being invoked in the main App template:
```jsx
const ListItem = (props) => {
return () =>
export default ListItem
```
### Router
This app requires a router to navigate between pages. This is done with the Framework7 builtin feature. You may pass entire app components to the router, as shown below.
```js
import Extra from '../components/extra.f7.jsx';
export default [
//{
// path: '/'
//},
{
path: '/extra/',
asyncComponent: () => Extra
}
]
```
### App init
Importantly, we only import Framework7 modules we need, to lighten the final bundle:
```js
import Dialog from 'framework7/esm/components/dialog/dialog.js';
import Gauge from 'framework7/esm/components/gauge/gauge.js';
import Panel from 'framework7/esm/components/panel/panel.js';
import View from 'framework7/esm/components/view/view.js';
Framework7.use([Dialog, Gauge, Panel, View]);
```
App UI is initialized passing the main app component, the routes and targeting the `#app` element, located within the `app_ui()` function:
```r
app_ui <- function(request) {
tagList(
# Leave this function for adding external resources
golem_add_external_resources(),
# Your application UI logic
tags$body(
div(id = "app"),
tags$script(src = "www/index.js")
)
)
}
```
Since the JS assets have to go after the `#app` element in the `body` tag, we had to comment out the `{golem}` predefined script:
```r
tags$head(
favicon(),
#bundle_resources(
# path = app_sys('app/www'),
# app_title = 'shinyFramework7'
#)
# Add here other external resources
# for example, you can add shinyalert::useShinyalert()
)
```
Whole `index.js` code:
```js
import 'shiny';
// Import Framework7
import Framework7 from 'framework7';
// Import Framework7 Styles
import 'framework7/framework7-bundle.min.css';
// Install F7 Components using .use() method on class:
import Dialog from 'framework7/esm/components/dialog/dialog.js';
import Gauge from 'framework7/esm/components/gauge/gauge.js';
import Panel from 'framework7/esm/components/panel/panel.js';
import View from 'framework7/esm/components/view/view.js';
Framework7.use([Dialog, Gauge, Panel, View]);
// Import App component
import App from './components/app.f7.jsx';
// Import other routes
import routes from './modules/routes.js';
// Initialize app
var app = new Framework7({
el: '#app',
theme: 'ios',
// specify main app component
routes: routes,
component: App
});
```
### Server
On the server side (R):
```r
observeEvent(TRUE, {
session$sendCustomMessage("init", colnames(mtcars))
})
observeEvent(input$alert, {
message(sprintf("Received from JS: %s", input$alert$message))
message(sprintf("App title is %s", input$alert$title))
})
observe({print(input$alert_opened)})
```
## Example
This is a basic example which shows you how to solve a common problem:
### Run app
```{r, eval=FALSE}
library(shinyComponent)
## basic example code
run_app()
```
### Dev mode
```{r, eval=FALSE}
library(shinyComponent)
## basic example code
packer::bundle_dev()
devtools::load_all()
run_app()
```