0
# Output Rendering
1
2
Shiny's rendering system converts Python objects into web-displayable content. Render functions create reactive outputs that automatically update when their dependencies change, supporting text, plots, tables, images, and dynamic UI content.
3
4
## Capabilities
5
6
### Text Rendering
7
8
Functions for rendering text content in various formats.
9
10
```python { .api }
11
def render.text(fn: Callable[[], str] | None = None, *, inline: bool = False) -> text:
12
"""
13
Render text output.
14
15
Args:
16
fn: Function that returns a string to display.
17
inline: Whether to render as inline text.
18
19
Returns:
20
Text renderer instance.
21
"""
22
23
def render.code(fn: Callable[[], str] | None = None, *, placeholder: bool = True) -> code:
24
"""
25
Render code block with syntax formatting.
26
27
Args:
28
fn: Function that returns code as a string.
29
placeholder: Whether to show placeholder when content is empty.
30
31
Returns:
32
Code renderer instance.
33
"""
34
```
35
36
#### Usage Examples
37
38
```python
39
# Basic text output
40
@output
41
@render.text
42
def summary():
43
return f"Dataset has {len(data())} rows and {len(data().columns)} columns"
44
45
# Multi-line text
46
@output
47
@render.text
48
def analysis_report():
49
stats = calculate_stats()
50
return f"""
51
Analysis Report
52
===============
53
Mean: {stats['mean']:.2f}
54
Median: {stats['median']:.2f}
55
Standard Deviation: {stats['std']:.2f}
56
"""
57
58
# Code output with syntax highlighting
59
@output
60
@render.code
61
def generated_code():
62
params = input.model_params()
63
return f"""
64
import pandas as pd
65
import numpy as np
66
67
# Generated model configuration
68
model = LinearRegression(
69
fit_intercept={params['fit_intercept']},
70
alpha={params['alpha']}
71
)
72
"""
73
```
74
75
### Plot Rendering
76
77
Support for rendering various plot types including matplotlib, plotly, and other visualization libraries.
78
79
```python { .api }
80
def render.plot(
81
fn: Callable[[], object],
82
*,
83
alt: str | None = None,
84
width: int | float | str = "auto",
85
height: int | float | str = "auto",
86
**kwargs: object
87
) -> OutputRenderer[object]:
88
"""
89
Render plot output.
90
91
Args:
92
fn: Function that returns a plot object (matplotlib, plotly, etc.).
93
alt: Alt text for accessibility.
94
width: Plot width in pixels or CSS units.
95
height: Plot height in pixels or CSS units.
96
**kwargs: Additional arguments passed to the plotting backend.
97
98
Returns:
99
Output renderer for plot content.
100
"""
101
```
102
103
#### Usage Examples
104
105
```python
106
import matplotlib.pyplot as plt
107
import plotly.express as px
108
import seaborn as sns
109
110
# Matplotlib plot
111
@output
112
@render.plot
113
def scatter_plot():
114
df = filtered_data()
115
116
plt.figure(figsize=(10, 6))
117
plt.scatter(df['x'], df['y'], alpha=0.6)
118
plt.xlabel(input.x_variable())
119
plt.ylabel(input.y_variable())
120
plt.title(f"Scatter Plot: {input.x_variable()} vs {input.y_variable()}")
121
plt.grid(True, alpha=0.3)
122
123
return plt.gcf() # Return current figure
124
125
# Plotly plot
126
@output
127
@render.plot
128
def interactive_plot():
129
df = filtered_data()
130
131
fig = px.scatter(
132
df,
133
x=input.x_var(),
134
y=input.y_var(),
135
color=input.color_var() if input.color_var() else None,
136
title="Interactive Scatter Plot",
137
hover_data=['id', 'category']
138
)
139
140
return fig
141
142
# Seaborn plot
143
@output
144
@render.plot(width=800, height=600)
145
def correlation_heatmap():
146
df = numeric_data()
147
148
plt.figure(figsize=(10, 8))
149
sns.heatmap(
150
df.corr(),
151
annot=True,
152
cmap='coolwarm',
153
center=0,
154
square=True
155
)
156
plt.title("Correlation Matrix")
157
158
return plt.gcf()
159
```
160
161
### Image Rendering
162
163
Render static and dynamic images from various sources.
164
165
```python { .api }
166
def render.image(
167
fn: Callable[[], ImgData | str | bytes | os.PathLike[str]],
168
**kwargs: object
169
) -> OutputRenderer[ImgData | str | bytes | os.PathLike[str]]:
170
"""
171
Render image output.
172
173
Args:
174
fn: Function that returns image data, file path, or ImgData dict.
175
**kwargs: Additional image attributes (alt, width, height, etc.).
176
177
Returns:
178
Output renderer for image content.
179
"""
180
```
181
182
#### Usage Examples
183
184
```python
185
import io
186
import base64
187
from PIL import Image
188
189
# Render image from file path
190
@output
191
@render.image
192
def logo():
193
return "static/company_logo.png"
194
195
# Generate image dynamically
196
@output
197
@render.image
198
def generated_chart():
199
# Create image using PIL
200
img = Image.new('RGB', (400, 300), color='lightblue')
201
draw = ImageDraw.Draw(img)
202
203
# Draw some content based on inputs
204
draw.text((20, 20), f"Value: {input.current_value()}", fill='black')
205
206
# Convert to bytes
207
img_bytes = io.BytesIO()
208
img.save(img_bytes, format='PNG')
209
img_bytes.seek(0)
210
211
return img_bytes.getvalue()
212
213
# Return ImgData dictionary for full control
214
@output
215
@render.image
216
def custom_image():
217
image_path = generate_custom_visualization(input.params())
218
219
return {
220
"src": image_path,
221
"width": "100%",
222
"height": "400px",
223
"alt": "Custom visualization based on user parameters",
224
"style": "border: 1px solid #ddd; border-radius: 4px;"
225
}
226
```
227
228
### Table Rendering
229
230
Render tabular data with basic formatting.
231
232
```python { .api }
233
def render.table(
234
fn: Callable[[], object],
235
**kwargs: object
236
) -> OutputRenderer[object]:
237
"""
238
Render table output.
239
240
Args:
241
fn: Function that returns tabular data (DataFrame, dict, list of dicts, etc.).
242
**kwargs: Additional table formatting options.
243
244
Returns:
245
Output renderer for table content.
246
"""
247
```
248
249
#### Usage Examples
250
251
```python
252
# Render pandas DataFrame
253
@output
254
@render.table
255
def data_summary():
256
df = filtered_data()
257
return df.describe()
258
259
# Render list of dictionaries
260
@output
261
@render.table
262
def results_table():
263
results = process_analysis()
264
return [
265
{"Metric": "Accuracy", "Value": results['accuracy'], "Threshold": 0.9},
266
{"Metric": "Precision", "Value": results['precision'], "Threshold": 0.8},
267
{"Metric": "Recall", "Value": results['recall'], "Threshold": 0.75}
268
]
269
270
# Render dictionary as key-value table
271
@output
272
@render.table
273
def configuration():
274
return {
275
"Model Type": input.model_type(),
276
"Training Size": len(training_data()),
277
"Features": ", ".join(input.selected_features()),
278
"Last Updated": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
279
}
280
```
281
282
### Data Frame Rendering
283
284
Interactive data frame rendering with advanced features like sorting, filtering, and editing.
285
286
```python { .api }
287
def render.data_frame(
288
fn: Callable[[], object],
289
*,
290
width: str | float = "fit-content",
291
height: str | float = "500px",
292
summary: bool | str = True,
293
filters: bool = False,
294
editable: bool = False,
295
**kwargs: object
296
) -> DataFrameRenderer:
297
"""
298
Render interactive data frame.
299
300
Args:
301
fn: Function that returns a pandas DataFrame or similar.
302
width: Data frame width.
303
height: Data frame height.
304
summary: Show summary information.
305
filters: Enable column filtering.
306
editable: Allow cell editing.
307
**kwargs: Additional data frame options.
308
309
Returns:
310
Data frame renderer with interaction capabilities.
311
"""
312
313
class DataGrid:
314
"""
315
Configuration for data grid rendering.
316
"""
317
def __init__(
318
self,
319
*,
320
filters: bool = False,
321
editable: bool = False,
322
summary: bool | str = True,
323
**kwargs: object
324
): ...
325
326
class DataTable:
327
"""
328
Configuration for data table rendering.
329
"""
330
def __init__(
331
self,
332
*,
333
page_size: int = 10,
334
searchable: bool = True,
335
sortable: bool = True,
336
**kwargs: object
337
): ...
338
```
339
340
#### Usage Examples
341
342
```python
343
# Basic interactive data frame
344
@output
345
@render.data_frame
346
def dataset_view():
347
return filtered_data()
348
349
# Data frame with filtering and editing
350
@output
351
@render.data_frame(
352
filters=True,
353
editable=True,
354
height="600px"
355
)
356
def editable_data():
357
return working_dataset()
358
359
# Data grid configuration
360
@output
361
@render.data_frame
362
def analysis_results():
363
df = compute_results()
364
365
# Configure as data grid
366
return render.DataGrid(
367
df,
368
filters=True,
369
summary="Data from analysis pipeline",
370
editable=False
371
)
372
373
# Data table with pagination
374
@output
375
@render.data_frame
376
def large_dataset():
377
df = get_large_dataset()
378
379
return render.DataTable(
380
df,
381
page_size=25,
382
searchable=True,
383
sortable=True
384
)
385
```
386
387
### UI Rendering
388
389
Render dynamic UI content that can change based on reactive state.
390
391
```python { .api }
392
def render.ui(
393
fn: Callable[[], Tag | TagChild | None]
394
) -> OutputRenderer[Tag | TagChild | None]:
395
"""
396
Render dynamic UI content.
397
398
Args:
399
fn: Function that returns UI elements (Tag, TagChild, or None).
400
401
Returns:
402
Output renderer for UI content.
403
"""
404
```
405
406
#### Usage Examples
407
408
```python
409
# Dynamic input controls
410
@output
411
@render.ui
412
def dynamic_inputs():
413
dataset_type = input.data_type()
414
415
if dataset_type == "csv":
416
return ui.div(
417
ui.input_file("csv_file", "Upload CSV file"),
418
ui.input_checkbox("has_header", "File has header row", True)
419
)
420
elif dataset_type == "database":
421
return ui.div(
422
ui.input_text("db_connection", "Database Connection String"),
423
ui.input_text("query", "SQL Query")
424
)
425
else:
426
return ui.p("Please select a data source type")
427
428
# Conditional content based on analysis
429
@output
430
@render.ui
431
def analysis_options():
432
if not data_loaded():
433
return ui.div(
434
ui.h4("No Data Loaded"),
435
ui.p("Please upload data to begin analysis")
436
)
437
438
df = current_data()
439
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
440
441
return ui.div(
442
ui.h4("Analysis Options"),
443
ui.input_select(
444
"x_variable",
445
"X Variable",
446
choices=numeric_cols
447
),
448
ui.input_select(
449
"y_variable",
450
"Y Variable",
451
choices=numeric_cols
452
),
453
ui.input_checkbox_group(
454
"analysis_types",
455
"Analysis Types",
456
choices=["correlation", "regression", "clustering"]
457
)
458
)
459
460
# Dynamic content with complex logic
461
@output
462
@render.ui
463
def status_dashboard():
464
system_status = check_system_status()
465
466
status_color = "success" if system_status["healthy"] else "danger"
467
468
return ui.div(
469
ui.div(
470
ui.h3("System Status", class_=f"text-{status_color}"),
471
ui.p(f"Status: {system_status['message']}"),
472
class_=f"alert alert-{status_color}"
473
),
474
ui.div(
475
[ui.p(f"{service}: {'✓' if status else '✗'}")
476
for service, status in system_status["services"].items()],
477
class_="service-status"
478
),
479
ui.div(
480
ui.input_action_button(
481
"refresh_status",
482
"Refresh Status",
483
class_="btn btn-secondary"
484
)
485
)
486
)
487
```
488
489
### Download Handling
490
491
Create downloadable files for users.
492
493
```python { .api }
494
def render.download(
495
fn: Callable[[str], None],
496
filename: str | Callable[[], str] | None = None,
497
media_type: str = "application/octet-stream"
498
) -> DownloadHandler:
499
"""
500
Create a download handler.
501
502
Args:
503
fn: Function that writes content to the provided file path.
504
filename: Default filename or function that returns filename.
505
media_type: MIME type of the downloaded content.
506
507
Returns:
508
Download handler for file downloads.
509
"""
510
511
class DownloadHandler:
512
"""
513
Handler for file downloads.
514
"""
515
def set_filename(self, filename: str | Callable[[], str]) -> None:
516
"""Set the download filename."""
517
518
def set_media_type(self, media_type: str) -> None:
519
"""Set the MIME type."""
520
```
521
522
#### Usage Examples
523
524
```python
525
# Download CSV data
526
@output
527
@render.download(filename="data_export.csv")
528
def download_csv(file):
529
df = filtered_data()
530
df.to_csv(file, index=False)
531
532
# Download plot as image
533
@output
534
@render.download(
535
filename=lambda: f"plot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png",
536
media_type="image/png"
537
)
538
def download_plot(file):
539
fig = generate_current_plot()
540
fig.savefig(file, format='png', dpi=300, bbox_inches='tight')
541
542
# Download analysis report
543
@output
544
@render.download(filename="analysis_report.pdf")
545
def download_report(file):
546
analysis_results = run_complete_analysis()
547
548
# Generate PDF report
549
pdf = create_pdf_report(analysis_results)
550
pdf.output(file)
551
552
# Dynamic filename and content
553
@output
554
@render.download()
555
def download_custom(file):
556
export_format = input.export_format()
557
data = current_dataset()
558
559
if export_format == "csv":
560
data.to_csv(file, index=False)
561
return f"data_export_{datetime.now().strftime('%Y%m%d')}.csv"
562
elif export_format == "json":
563
data.to_json(file, orient='records', indent=2)
564
return f"data_export_{datetime.now().strftime('%Y%m%d')}.json"
565
elif export_format == "excel":
566
data.to_excel(file, index=False)
567
return f"data_export_{datetime.now().strftime('%Y%m%d')}.xlsx"
568
```
569
570
### Express Rendering
571
572
Special rendering decorator for Express mode applications.
573
574
```python { .api }
575
def render.express(
576
fn: Callable[[], object]
577
) -> object:
578
"""
579
Express-style rendering decorator.
580
581
Args:
582
fn: Function that returns content to render.
583
584
Returns:
585
Rendered content for Express mode.
586
"""
587
```
588
589
#### Usage Examples
590
591
```python
592
# Express mode rendering (in express apps)
593
from shiny.express import render, input, ui
594
595
# Automatic output binding in Express mode
596
@render.text
597
def current_status():
598
return f"Processing {input.selected_file()}"
599
600
@render.plot
601
def main_visualization():
602
return create_plot(input.parameters())
603
604
# Express rendering works with all render types
605
@render.data_frame
606
def results_table():
607
return analyze_data(input.dataset(), input.options())
608
```
609
610
### Render Transformers
611
612
Utilities for transforming render output.
613
614
```python { .api }
615
class render.transformer:
616
"""
617
Utilities for transforming render output.
618
"""
619
@staticmethod
620
def cache_disk(
621
cache_dir: str | os.PathLike[str] | None = None,
622
max_size: int | None = None
623
) -> Callable[[Callable], Callable]: ...
624
625
@staticmethod
626
def cache_memory(
627
max_size: int = 128
628
) -> Callable[[Callable], Callable]: ...
629
```
630
631
#### Usage Examples
632
633
```python
634
# Cache expensive computations to disk
635
@output
636
@render.plot
637
@render.transformer.cache_disk(cache_dir="./plot_cache", max_size=100)
638
def expensive_plot():
639
# This plot will be cached to disk
640
return generate_complex_visualization(large_dataset())
641
642
# Cache in memory
643
@output
644
@render.table
645
@render.transformer.cache_memory(max_size=50)
646
def analysis_summary():
647
# Results cached in memory
648
return compute_summary_statistics(input.dataset())
649
```