How the components meet Shiny: what they report, how the server reaches them, how they behave in modules, with bookmarks and alongside the rest of the Shiny ecosystem, and how to build components of your own. Each component’s own page – under Components – shows what Element does with it.
A component reports to input$<id>, on load as well as on change:
ui <- el_page(
el_select("city", choices = c("Beijing", "Shanghai"), value = "Shanghai"),
verbatimTextOutput("picked")
)
server <- function(input, output, session) {
output$picked <- renderPrint(input$city)
}
shinyApp(ui, server)Three separate channels reach back into it, and they do different things:
| Reaches | Example | |
|---|---|---|
update_el_*() |
the component’s props | update_el_select(session, "city", selected = "Beijing") |
call_el() |
the component’s methods | call_el(session, "tbl", "clearSelection") |
update_vue() |
the Vue instance’s fields directly | update_vue(session, "tip", tipContent = "...") |
Like Shiny’s update*Input(), each takes the current session by default, so update_el_select(id = "city", selected = "Beijing") is the same call. An update reaches a component whether or not it has a value to report – an alert, a timeline, a component only ever drawn by renderUI() – and one sent to an id that is not on the page, or to a field the component does not have, logs a [shiny-vue] warning in the browser console rather than vanishing.
update_el_*() cannot call a method, because it assigns into the Vue instance’s data and a method is a function. That is what call_el() is for. A method with a return value answers asynchronously, as input$<id>_<method>:
ui <- el_page(
el_tree(
"tree",
show_checkbox = TRUE,
node_key = "id",
default_expand_all = TRUE,
default_checked_keys = c("b1", "c"),
data = list(
list(
id = "a",
label = "Fruit",
children = list(
list(id = "b1", label = "Apple"),
list(id = "b2", label = "Pear")
)
),
list(id = "c", label = "Bread")
)
),
el_button("ask", "Which are checked?"),
verbatimTextOutput("answer")
)
server <- function(input, output, session) {
observeEvent(input$ask, call_el(session, "tree", "getCheckedKeys"))
output$answer <- renderPrint(input$tree_get_checked_keys)
}
shinyApp(ui, server)As with Shiny’s own update*Input(), an update or a method call for a component that is not on the page yet – one a renderUI() has still to draw – is dropped, with a [shiny-vue] warning in the browser’s console. Send it from an observer that runs once the component is there, as for any Shiny input.
Shiny’s own update*Input() do not send at once: the message waits for the flush, and goes with the outputs that the same observers recalculated. The updates and method calls here do the same – every update_el_*(), call_el(), update_vue(), call_vue() – so a component an observer re-renders and updates is updated once drawn again. A progress bar is the exception, as withProgress() is: update_el_progress() is sent at once.
An update made before a long computation in the same observer therefore shows after it. flush_vue() sends what is queued at once:
observeEvent(input$run, {
flush_vue({
update_el_table(session, "tbl", loading = TRUE)
})
result <- slow_query() # the table shows its mask meanwhile
update_el_table(session, "tbl", data = result, loading = FALSE)
})Often there is a better way. A computation in an ExtendedTask leaves the observer at once, and its updates go with that flush. A button that shows it is working needs no server at all: el_button(task = TRUE) turns to Element’s loading state in the browser when clicked, and back once the server has handled the click – or, bound with bslib::bind_task_button(), once the task is done – as bslib’s input_task_button():
ui <- el_page(el_button("save", "Save", type = "primary", task = TRUE))
server <- function(input, output, session) {
save <- ExtendedTask$new(function() {
promises::promise(function(resolve, reject) {
later::later(function() resolve(TRUE), 3)
})
})
bslib::bind_task_button(save, "save")
observeEvent(input$save, save$invoke())
}
shinyApp(ui, server)A component reports its value, the actions a user takes on purpose – confirming, closing, submitting, going back – and the requests the server answers, such as a remote search’s text or a lazy node asking for its children. Element’s other events – focus and blur, hovering, a dropdown opening, a drag in progress – stay in the browser until asked for: each would be a message to the server, and most apps never read them.
Ask for one with events, by Element’s name in snake_case; it arrives as input$<id>_<event>. el_events() lists what a component reports, and which it reports unasked; its help page lists the same under “Shiny inputs”, and a name it does not have is an error that lists them:
el_events("el_tree")
#> el_tree() reports, as input$<id>...:
#>
#> Unasked
#> input$<id> the key of the node last clicked
#> input$<id>_checked the keys of the checked nodes
#> input$<id>_load with `lazy = TRUE`, a node asking for its children; ...
#>
#> When asked for, with `events =`
#> input$<id>_check_change `list(data, checked, indeterminate)`
#> input$<id>_node_drop `list(dragging, drop, type)`: ...
#> ...
el_tree("tree", data = tree_data, draggable = TRUE, events = "node_drop")
# -> input$tree_node_dropFor an event Element does not list – a key with a modifier, a DOM event on the element it draws – or to send something else than an event carries, give the component a handler of your own with on: a JS() function called with report and the event’s arguments. report(name, value) sets input$<id>_<name>, namespaced in a module as the id is, the same rule as every other input:
ui <- el_page(
el_input(
"q",
placeholder = "Type, then Enter",
on = list(
"keyup.enter" = JS("function(report, e) { report('enter', e.target.value); }")
)
),
verbatimTextOutput("searched")
)
server <- function(input, output, session) {
# input$q follows each keystroke; input$q_enter, only Enter
output$searched <- renderText(paste("searched for:", input$q_enter))
}
shinyApp(ui, server)Every forwarded Element event sets its input with event priority. The input keeps its last value like any other; what event priority adds is that sending the same value again still counts as a change. Clicking the same row twice fires an observeEvent() twice – while an output that only reads the value sees nothing new the second time.
Here is the same row clicked twice. The output reading the value shows where the last click landed; only the observer knows there were two:
ui <- el_page(
el_table_output("tbl"),
verbatimTextOutput("polled"),
verbatimTextOutput("latched")
)
server <- function(input, output, session) {
output$tbl <- render_el_table(
el_table(data = head(iris[, c(1, 5)], 3), events = "row_click")
)
# Reading the value: the last row clicked, but not how many times
output$polled <- renderText({
paste("last row clicked:", input$tbl_row_click$row_index)
})
# Observing the event: runs once per click, repeats included
clicks <- reactiveVal(0)
observeEvent(input$tbl_row_click, clicks(clicks() + 1))
output$latched <- renderText(paste("clicks seen:", clicks()))
}
shinyApp(ui, server)An event whose arguments cannot cross the wire – a native FocusEvent, a DOM node, a whole Vue instance – reports TRUE instead, so an observer can still tell that it happened.
Components follow Shiny’s own rule. In a module’s UI, the id is wrapped in ns(), exactly as for textInput(); in its server, input$<id> and every update_el_*() take the bare id, namespaced by the module’s session. That holds for UI built by renderUI() inside the module too, and for the inputs a component adds to its id – input$rows_go from a row action, input$tabs_tab_remove, input$rows_selection_change. An output is the same: el_table_output(ns("rows")) in the UI, output$rows in the server.
orders_ui <- function(id) {
ns <- NS(id)
tagList(
el_select(ns("status"), choices = c("paid", "pending"), selected = "paid"),
el_table_output(ns("rows")),
uiOutput(ns("more")),
verbatimTextOutput(ns("seen"))
)
}
orders_server <- function(id) {
moduleServer(id, function(input, output, session) {
output$rows <- render_el_table(el_table(
data = data.frame(order = c(101, 102)),
columns = list(
list(prop = "order", label = "Order"),
list(
label = "",
cell = el$button(
size = "small",
"@click" = "rowAction('open', scope)",
"Open"
)
)
)
))
# Built in the server, still wrapped in ns() once
output$more <- renderUI(el_switch(
session$ns("urgent"),
active_text = "Urgent"
))
output$seen <- renderPrint(list(
status = input$status,
urgent = input$urgent,
opened = input$rows_open$row_index
))
})
}
ui <- el_page(orders_ui("orders"))
server <- function(input, output, session) orders_server("orders")
shinyApp(ui, server)Before 0.1.0 the UI functions namespaced their id themselves, from the session they were built in – which inside renderUI() in a module turned ns("urgent") into "orders-orders-urgent", an input that never reported. They no longer do; their session argument is deprecated, and a session passed to it still namespaces, with a warning.
Each component is a Shiny input binding on a host element that carries its id, so the tools that work on Shiny’s inputs work on these.
Bookmarking. Under enableBookmarking(), every component’s value comes back from a bookmark – including where a container is: the open tab, the open panels of a collapse, an open dialog or drawer, the menu’s current item, the pager’s page. Nothing needs to be set up beyond what Shiny itself asks for.
ui <- function(request) {
el_page(
el_select("city", choices = c("Beijing", "Shanghai")),
el_tabs(
"views",
tabs = list(
list(name = "table", label = "Table", content = tags$p("...")),
list(name = "chart", label = "Chart", content = tags$p("..."))
)
),
bookmarkButton()
)
}
server <- function(input, output, session) {}
shinyApp(ui, server, enableBookmarking = "url")shinyjs. shinyjs::hide() and show() take the component and its label with it; disable() and enable() set the component’s own disabled, so it is drawn disabled as Element draws it rather than having a native attribute set somewhere underneath. reset() puts the components under the element it is given back as the page first had them, beside Shiny’s own inputs; to set any other value, use the component’s update_el_*(). hidden() and disabled() wrap a component in the UI, click() clicks the button or link inside it, and onclick() and onevent() hear events from inside it. addClass() puts a class on the component’s host, which draws no box of its own (display: contents): style the component with its own class argument instead.
bslib. Components work in bslib’s containers – a sidebar, a card, an accordion, a nav panel not yet shown – and bslib’s tooltip() and popover() take one as their trigger. bslib’s input_dark_mode() turns Element Plus’s dark mode with Bootstrap’s. Element’s brand colours follow Bootstrap’s CSS variables, so a theme changed while the app runs – session$setCurrentTheme(), bslib::bs_themer() – recolours Element’s components too.
Busy indicators. Under useBusyIndicators() a table output keeps Element’s own loading mask while it recalculates, in place of Shiny’s spinner; el_table_output(loading = FALSE) gives it Shiny’s.
Asynchronous work. Every render function waits for a promise, so the result of an ExtendedTask or a promises pipeline can be rendered as a table or as a component’s data.
Inserting and removing. insertUI() and renderUI() mount what they add; removeUI() on a component’s id removes it and destroys its Vue instance, so it stops reporting.
Validation. shinyvalidate draws its message the way Element draws a failed rule; see the forms article.
Testing. shinytest2’s set_inputs() and get_values() read and write a component as they do a textInput(). An input with no component of its own behind it – a table’s _selection_rows, an event such as _row_click – has no input binding, so set_inputs() needs allow_no_input_binding_ = TRUE for it, and sets the server’s value only: the page does not tick the rows.
Two kinds of component wrap other content, and they behave differently.
Containers are plain markup. el_row(), el_col(), el_container(), el_collapse(), el_tabs(), el_dialog() and el_drawer() render Element’s own CSS classes and drive their state through a Shiny input binding. They hold anything, and what is inside keeps working as it would on its own.
el_collapse(
"panels",
value = "one",
items = list(
list(
name = "one",
title = "Settings",
content = tagList(
el_switch("dark", value = TRUE, active_text = "Dark mode"),
el_rate("stars", value = 4)
)
),
list(name = "two", title = "About", content = tags$p("Version 0.1.0"))
)
)Wrappers absorb what they are given. el_tooltip(), el_popover(), el_popconfirm() and el_infinite_scroll() compile their content into their own Vue instance, so a component handed to one is folded in rather than nested: the two become a single instance carrying both sets of markup, data and methods.
ui <- el_page(
el_tooltip("hint", el_button("save", "Save", type = "primary"),
content = "Writes to disk", placement = "right"),
verbatimTextOutput("clicks")
)
server <- function(input, output, session) {
output$clicks <- renderText(paste("Saved", input$save, "times")) # still reports
}
shinyApp(ui, server)An absorbed component has no host of its own, but it keeps its id: the wrapper lists the components it took in, and update_el_*() and call_el() for that id reach it through the wrapper’s instance. In the page the id is on the component itself, as Element hands it on – a button’s <button>, an input’s <input> – rather than on a host around it.
ui <- el_page(
el_tooltip(
"hint",
el_button("save", "Save", type = "primary"),
content = "Writes to disk"
),
el_button("busy", "Mark as saving")
)
server <- function(input, output, session) {
observeEvent(input$busy, {
update_el_button(session, "save", label = "Saving...", loading = TRUE)
})
}
shinyApp(ui, server)If two absorbed components declare the same field – most declare a label, a type and a disabled – the second one’s fields are renamed on the way in (el3_label), and the markup that names them is rewritten to match. Updates by the component’s id follow the renaming; update_vue() on the wrapper’s id sets the fields under the names they have there.
Every component takes slots, a named list:
el_alert(
"problem",
type = "error",
show_icon = TRUE,
description = "The upload was larger than 5 MB.",
slots = list(title = tags$span(tags$b("Upload failed"), " -- try again"))
)A scoped slot – one where Element hands the template variables that only exist while Vue renders – is written with template() and passed through untouched:
el_calendar(
"cal",
value = "2026-03-15",
slots = list(
dateCell = template(
htmltools::HTML(paste0(
"<div>{{ data.day.slice(8) }}",
"<b v-if=\"data.day.slice(8) === '15'\" style=\"color:#F56C6C\">",
" due</b></div>"
)),
slot = "dateCell",
scope = "{date, data}"
)
)
)Filling a slot replaces what Element put there, default and all. Element’s el-form-item error slot, for instance, wraps the message in div.el-form-item__error; a template that renders only the message loses the styling with it.
el holds a generator for every Element tag, for markup that needs no Vue instance of its own – inside one that already exists. Vue compiles <el-*> tags only within the component it mounts, so a raw tag goes where a component draws its contents: a template(), a slot, a table cell, a wrapper’s trigger.
# The tooltip's instance compiles the raw button it wraps
el_tooltip(
"hint",
el$button(type = "primary", "Markup only"),
content = "No input"
)
el_button("save", "A component", type = "primary") # reports input$savePlaced at the top level of a page, the same el$button() is never compiled and shows as its bare text. Use the raw tag where a component would be wasted, and a component where the server needs to hear about it.
Every component in this package is a Vue component on a host element that carries its id, with a Shiny input binding on it – the way reactR binds React components – so the rest of Shiny reaches it: shinyjs::hide(), removeUI(), a test driver’s set_inputs(), bookmarks. The layer that does this is exported, and knows nothing of Element: vue_app() writes a Vue component in R.
The arguments of vue_app() are the options of a Vue 3 component – template, data, methods, computed, watch, emits, setup, components, the lifecycle hooks – under Vue’s own names (a multi-word one also as snake_case: before_unmount). Three things are added, as Shiny needs them: id, where the component goes and what the server calls it; input, the field that is input$<id>; and dependencies. use is Vue’s app.use().
ui <- fluidPage(
vue_app(
"counter",
template = tags$div(
tags$button(`@click` = "n++", "Add one"),
tags$span(" clicked {{ n }} times, {{ doubled }} doubled")
),
data = list(n = 0),
computed = list(doubled = JS("function() { return this.n * 2; }")),
input = "n"
),
verbatimTextOutput("n")
)
server <- function(input, output, session) {
output$n <- renderPrint(input$counter)
}
shinyApp(ui, server)| Vue | In R |
|---|---|
createApp(options).mount('#app') |
vue_app(id, ...) |
data(), methods, computed, watch, hooks |
the same names; functions written with JS() |
setup() (the Composition API) |
setup = JS("function() { ... }") |
app.use(Plugin, options) |
use = list(Plugin = options) |
| the component’s value | input = "<field>", reported as input$<id> |
| its input handler and rate | type = "shiny.date", rate = "debounce", as Shiny’s inputs have |
this.$emit("picked", x) |
input$<id>_picked, for an event listed in emits |
| an event of the template’s root – a library’s component there | events = "row_click" → input$<id>_row_click |
| a handler of one’s own | on = list(click = JS("function(report, e) { report('x', 1); }")) |
| a child component | components = list(todo_item = vue_component(...)) |
app.config, a plugin written here |
use = JS("{ install(app) { ... } }") |
A component’s value is one field, or several (input = c("from", "to")) for one value that is a named list – input$<id>$from, input$<id>$to, never an input per field – as dateRangeInput() gives one value of two dates. Anything else it sends out goes Vue’s way, with $emit(), and arrives with event priority under the component’s id, as Element’s own events do: $emit("picked", x) is input$<id>_picked holding x; several arguments are a list, arg1, arg2, …; none is TRUE. Inside a module, wrap the id in ns(); the events follow it.
data is the initial state as R writes it: a list is an object, a data.frame its rows – a data.frame further in, or a list column, too. A vector of one element is a single value, as everywhere in Shiny: c("a", "b") is an array, "a" a string. Where JavaScript expects an array whatever its length – a list of tags, v-for over it – wrap it in I(): list(tags = I("red")) is {"tags": ["red"]}. Show a user’s data through it – {{ field }}, :prop="field" – which Vue renders as text. Never paste it into the template: a template is code, and {{ }} in it runs.
| Function | Does | Shiny’s own |
|---|---|---|
update_vue(session, id, field = value, value =) |
sets fields of the component’s state; value is its input field |
update*Input() |
call_vue(session, id, method, args) |
runs a method; its result comes back as input$<id>_<method> |
– |
vue_answer(session, id, request, value) |
answers a component that asked the server (shinyVue.ask()) |
– |
vue_output(id) / render_vue(expr) |
draws components from the server, keeping the user’s state | uiOutput() / renderUI() |
vue_app(outputs =) / render_vue_data(expr) |
sets data fields by name from an output: values, not markup | shinyreact’s reactive_output() |
update_vue() replaces a field whole. A long list, or a deep object, can be changed in place, sending only what changes – rows inserted, replaced or deleted, by position or by a key field, and values set by path:
update_vue(
session,
"todo",
insert = list(items = list(id = "t9", text = "Call Ann")),
at = 1
)
update_vue(session, "todo", replace = list(items = changed_rows), key = "id")
update_vue(session, "todo", delete = list(items = c("t2", "t5")), key = "id")
update_vue(
session,
"todo",
set = list("items[3].done" = TRUE, "user.name" = "Ann")
)The table’s and the calendar’s insert, replace and delete are built on the same.
render_vue() differs from renderUI() in one way: a render that changes only a component’s data updates that component instead of replacing it, so what the user did – a sort, a tick, an open tab – stays. A render that changes the structure replaces it, as renderUI() would. Put what changes from render to render in data, and keep the template the same.
Two outputs, by who writes the component. render_vue() draws one the server writes – template, options, methods and data, any of which a render can change – as shiny.react’s renderReact() draws React. Where the component is written in the UI and only its data comes from the server, the component names an output in outputs and its data follows it: render_vue_data() renders data fields by name – list(mean = 1, sd = 2), each value a number, a list, a data.frame’s rows, a [JS()] function – and the fields it names take those values, as update_vue() would set them. As there, a field must be declared in data: Vue tracks only the fields a component starts with. It is an output as Shiny knows them: it runs again when what it reads changes, waits while its component is hidden, waits for a promise, and while it runs $recalculating.<id> is true, for the template to say so.
ui <- fluidPage(
sliderInput("n", "Draws", 10, 1000, 100),
vue_app(
"summary",
tags$p(
`:style` = "{opacity: $recalculating.stats ? 0.4 : 1}",
"Mean {{ mean }}, sd {{ sd }} of {{ n }} draws"
),
data = list(mean = NA, sd = NA, n = 0),
outputs = "stats"
)
)
server <- function(input, output, session) {
output$stats <- render_vue_data({
x <- rnorm(input$n)
list(mean = round(mean(x), 2), sd = round(sd(x), 2), n = input$n)
})
}
shinyApp(ui, server)Inside a module the id is wrapped, as any output’s is: outputs = ns("stats"). A component can follow several outputs, each setting its own fields: outputs = c("stats", "trend").
One output can feed several components, or a vue_store() that every component reads – the shared state Vue’s guide recommends, with the server as its source:
ui <- fluidPage(
vue_store("sales", data = list(revenue = 0, growth = 0), outputs = "totals"),
vue_app("kpi", tags$b("{{ $store.sales.revenue }}")),
vue_app("trend", tags$i("{{ $store.sales.growth }} %"))
)
server <- function(input, output, session) {
output$totals <- render_vue_data({
s <- summarise_sales(input$region)
list(revenue = s$revenue, growth = s$growth)
})
}render_vue(), render_vue_data() and render_el_table() can be cached with bindCache(), as Shiny’s own render functions can. A table output caches the table as rendered, the same for every session; read back from the cache, it is still compared with what each page has, so the page gets only what changed.
| In a template | Is |
|---|---|
$inputs.<id> |
another input’s value, as the server has it (read-only) |
$recalculating.<id> |
true while a render_vue_data() output recalculates |
$errors.<id> |
its error, {message, type}, until it renders again |
$busy |
true while the server works |
$setInput(name, value) |
sets input$<name>, as Shiny.setInputValue() |
A component written with the Composition API reads the same through composables, as shinyreact’s hooks:
vue_app(
"summary",
tags$p(
"{{ n }} rows, {{ stats.value && stats.value.mean }}",
"{{ busy ? '...' : '' }}"
),
setup = JS(
"function() {
return {
pick: shinyVue.useInput('pick', 'a'), // a ref, sent as input$pick
n: shinyVue.useInputValue('rows'), // another input's value
stats: shinyVue.useOutput('stats'), // {value, recalculating, error}
busy: shinyVue.useBusy()
};
}"
)
)A template can hold Shiny’s own UI – an input, a plot, a DT table, an htmlwidget, another component, a conditionalPanel() – even where Vue shows and hides it with v-if. It is taken out of the template and rendered beside it, as Shiny renders it; Vue moves it in where it stands and back out when it hides it, so its binding and the user’s input stay, and an output hidden this way waits, as one in a hidden tab does:
ui <- fluidPage(
vue_app(
"panel",
tags$div(
tags$label(
tags$input(type = "checkbox", `v-model` = "open"),
" Show the plot"
),
tags$div(
`v-if` = "open",
selectInput("var", "Variable", names(mtcars)),
plotOutput("hist", height = "250px")
)
),
data = list(open = TRUE)
)
)
server <- function(input, output, session) {
output$hist <- renderPlot(hist(mtcars[[input$var]], main = input$var))
}
shinyApp(ui, server)A piece of UI takes one place: inside a v-for it would be wanted in several, and only the first gets it.
el_widget() is vue_app() with Element Plus installed and a label in Element’s form-item style – what every component in this package is made of. A price range made of two number inputs, reported as one value:
price_range_input <- function(id, value = c(0, 100), min = 0, max = 1000) {
el_widget(
id = id,
markup = tags$div(
style = "display: flex; align-items: center; gap: 8px",
el$input_number(
"v-model" = "range[0]",
":min" = "min",
":max" = "range[1]",
"controls-position" = "right",
size = "small"
),
tags$span("to"),
el$input_number(
"v-model" = "range[1]",
":min" = "range[0]",
":max" = "max",
"controls-position" = "right",
size = "small"
)
),
data = list(range = as.list(value), min = min, max = max),
input = "range",
dependency = element_plus_dependency()
)
}
ui <- el_page(
price_range_input("price", value = c(20, 300)),
el_button("cheap", "Under 50"),
verbatimTextOutput("picked")
)
server <- function(input, output, session) {
observeEvent(input$cheap, update_vue(session, "price", value = list(0, 50)))
output$picked <- renderPrint(input$price)
}
shinyApp(ui, server)The components also work on a page with no Shiny session – an R Markdown or Quarto document, a page saved with htmltools::save_html(). They render and respond: a select opens and picks, tabs switch, a collapse folds, a table’s rows tick. What they cannot do there is report: there is no input, and update_el_*(), call_el() and the feedback functions have no server to come from. Load the scripts once with use_element(), as for any page that is not an el_page(). The examples on this website are built exactly so.
Where Element takes a JavaScript function to fetch data, the server can answer instead, through an input and an update:
| Component | Asks through | Answered by |
|---|---|---|
el_select(remote = TRUE) |
input$<id>_query |
update_el_select(choices =) |
el_autocomplete(remote = TRUE) |
input$<id>_query |
update_el_autocomplete(suggestions =) |
el_tree(lazy = TRUE) |
input$<id>_load |
el_load_children() |
el_cascader(props = list(lazy = TRUE)) |
input$<id>_lazy_load |
el_load_children() |
el_table(lazy = TRUE) |
input$<id>_load |
el_load_children() |
el_infinite_scroll() |
input$<id>_load |
a uiOutput() inside it |
el_pagination() |
input$<id>, the page |
update_el_table(data =) |
A question the server never answers settles after 30 seconds – a lazy load with nothing, a remote search by leaving its loading state – and a lazy load’s question settles at once when its component is removed or the session ends. The Select, Input, Tree, Cascader and Table pages show each one running.