Skip to content

Commit 0f477ef

Browse files
committed
Update custom renderers example
1 parent b43818b commit 0f477ef

6 files changed

Lines changed: 153 additions & 121 deletions

File tree

aidbox-forms/aidbox-forms-builder-custom-renderer/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ COPY Caddyfile /etc/caddy/Caddyfile
66
# Copy the HTML and JS files to caddy directory
77
WORKDIR /srv
88
COPY ./smartforms-component/dist/aidbox-forms-renderer-csiro-webcomponent.js /srv/
9+
COPY ./simple-questionnaire-renderer.js /srv/
910

1011
# Expose port 80
1112
EXPOSE 80
1213

1314
# Start caddy
14-
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
15+
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]

aidbox-forms/aidbox-forms-builder-custom-renderer/README.md

Lines changed: 85 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,58 +4,49 @@ languages: [JavaScript]
44
---
55
# Custom Renderer Tutorial for Aidbox Forms Builder
66

7-
This tutorial demonstrates how connect a custom renderer to the Aidbox Forms Builder preview.
7+
This tutorial demonstrates how to connect a custom renderer to the Aidbox Forms Builder preview.
88

99
## Overview
1010

1111
The Aidbox Forms Builder allows you to use custom renderers to display questionnaires with your own UI components. This example shows how to:
1212

13-
1. Wrap your renderer to webcomponent
13+
1. Wrap your renderer as a web component
1414
2. Host and configure it with Aidbox
1515
3. Use it in the Forms Builder preview
1616

17-
## Quick Start
18-
19-
### Prerequisites
17+
## Prerequisites
2018

2119
- Docker and Docker Compose
2220
- Aidbox license (get one from [Aidbox Console](https://aidbox.io))
2321

24-
### Setup
22+
## Tutorial
2523

26-
1. **Clone and configure:**
27-
```bash
28-
git clone <this-repo>
29-
cd aidbox-forms-builder-custom-renderer
30-
cp .env.example .env
31-
# Add your AIDBOX_LICENSE to .env
32-
```
24+
### Step 1: Clone and Configure
3325

34-
2. **Build the smartforms component:**
35-
```bash
36-
cd smartforms-component
37-
npm install
38-
npm run build
39-
cd ..
40-
```
26+
```bash
27+
git clone <this-repo>
28+
cd aidbox-forms-builder-custom-renderer
29+
cp .env.example .env
30+
# Add your AIDBOX_LICENSE to .env
31+
```
4132

42-
3. **Start services:**
43-
```bash
44-
docker-compose up -d
45-
```
33+
### Step 2: Build the Smartforms Component
4634

47-
4. **Access the services:**
48-
- Aidbox: http://localhost:8080
49-
- Custom renderer demo: http://localhost:8081
35+
This example includes a CSIRO Smartforms renderer wrapped as a web component. Build it first:
5036

51-
## Tutorial Steps
37+
```bash
38+
cd smartforms-component
39+
npm install
40+
npm run build
41+
cd ..
42+
```
5243

53-
### Step 2. Wrap your renderer for Forms Builder Compatibility
44+
### Step 3: Wrap Your Renderer for Forms Builder Compatibility
5445

55-
The Forms Builder expects a specific web component structure. Use the provided template:
46+
The Forms Builder expects a specific web component structure. Use the provided template `custom-renderer.template.js`:
5647

5748
```javascript
58-
// wrapped-questionnaire-renderer.js
49+
// custom-renderer.template.js
5950
if(!customElements.get("questionnaire-custom-renderer")) {
6051

6152
class QuestionnaireCustomRenderer extends HTMLElement {
@@ -67,13 +58,37 @@ class QuestionnaireCustomRenderer extends HTMLElement {
6758
this._onQuestionnaireResponseChange = null;
6859
}
6960

70-
// Must implement these exact methods:
61+
static get observedAttributes() {
62+
return ['questionnaire', 'questionnaire-response'];
63+
}
64+
65+
// Handle attribute updates from Forms Builder
66+
attributeChangedCallback(name, oldValue, newValue) {
67+
if (!this.shadowRoot || oldValue === newValue) return;
68+
69+
try {
70+
const parsed = newValue ? JSON.parse(newValue) : null;
71+
if (name === 'questionnaire') this._questionnaire = parsed;
72+
if (name === 'questionnaire-response') this._questionnaireResponse = parsed;
73+
this.render();
74+
} catch (e) {
75+
console.error(`Invalid JSON for ${name}:`, e);
76+
}
77+
}
78+
79+
// Property accessors
80+
get questionnaire() { return this._questionnaire; }
81+
set questionnaire(value) { this._questionnaire = value; this.render(); }
82+
83+
get questionnaireResponse() { return this._questionnaireResponse; }
84+
set questionnaireResponse(value) { this._questionnaireResponse = value; this.render(); }
85+
7186
set onQuestionnaireResponseChange(callback) {
7287
this._onQuestionnaireResponseChange = callback;
7388
}
7489

75-
// Your custom rendering logic goes in render()
7690
render() {
91+
if (!this.shadowRoot) return;
7792
// Implement your questionnaire rendering here
7893
}
7994
}
@@ -84,34 +99,37 @@ customElements.define('questionnaire-custom-renderer', QuestionnaireCustomRender
8499

85100
The only required attribute is `questionnaire`.
86101
Support `questionnaire-response` to receive populated QuestionnaireResponse.
87-
Support `onQuestionnaireResponseChange` if you want to send QuestionnaireResponse back to builder.
102+
Support `onQuestionnaireResponseChange` if you want to send QuestionnaireResponse back to the builder.
88103

89-
In this tutorial we will use `simple-questionnaire-renderer.js`
104+
This tutorial includes `simple-questionnaire-renderer.js`, a reference implementation that renders FHIR Questionnaires using native HTML inputs.
90105

91-
### Step 3: Host Your Renderer
106+
### Step 4: Host Your Renderer
92107

93-
Webcomponent should be accessible publicly.
94-
95-
In this tutorial we create a simple web server to host your renderer:
108+
The web component must be accessible via URL. This tutorial uses Caddy to serve the renderer files:
96109

97110
```dockerfile
98111
# Dockerfile
99112
FROM caddy:alpine
100113
COPY Caddyfile /etc/caddy/Caddyfile
101114
WORKDIR /srv
102115
COPY ./smartforms-component/dist/aidbox-forms-renderer-csiro-webcomponent.js /srv/
116+
COPY ./simple-questionnaire-renderer.js /srv/
103117
EXPOSE 80
104118
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
105119
```
106120

107-
### Step 4: Configure Aidbox
121+
### Step 5: Configure Aidbox
122+
123+
To register custom renderers with Aidbox Forms, update the `SDCConfig` resource.
108124

109-
To tell aidbox forms there are other renderers update the SDCConfif resource.
125+
Each renderer in the `custom-renderers` array requires:
126+
- **`name`** - The HTML tag name of your web component (e.g., `simple-questionnaire-renderer`)
127+
- **`source`** - URL where the renderer JavaScript file is hosted
128+
- **`title`** - Display name shown in the Forms Builder renderer dropdown
110129

111-
Create an initialization bundle to configure the custom renderer:
130+
Create an initialization bundle (`init-bundle.json`) to configure the custom renderers:
112131

113-
```yaml
114-
# init-bundle.yaml
132+
```json
115133
{
116134
"resourceType" : "Bundle",
117135
"type" : "transaction",
@@ -122,11 +140,18 @@ Create an initialization bundle to configure the custom renderer:
122140
"default": true,
123141
"id" : "custom-renderer-config",
124142
"builder": {
125-
"custom-renderers": [{
126-
"name" : "simple-questionnaire-renderer",
127-
"source" : "http://localhost:8081/simple-questionnaire-renderer.js",
128-
"title" : "Simple Questionnaire Renderer"
129-
}]
143+
"custom-renderers": [
144+
{
145+
"name" : "aidbox-form-csiro-renderer",
146+
"source" : "http://localhost:8081/aidbox-forms-renderer-csiro-webcomponent.js",
147+
"title" : "CSIRO"
148+
},
149+
{
150+
"name" : "simple-questionnaire-renderer",
151+
"source" : "http://localhost:8081/simple-questionnaire-renderer.js",
152+
"title" : "Simple Questionnaire Renderer"
153+
}
154+
]
130155
}
131156
},
132157
"request" : {
@@ -137,13 +162,22 @@ Create an initialization bundle to configure the custom renderer:
137162
}
138163
```
139164

140-
## Using in Forms Builder
165+
### Step 6: Start Services
166+
167+
```bash
168+
docker-compose up -d --pull always --build
169+
```
170+
171+
### Step 7: Use in Forms Builder
141172

142173
1. **Access Forms Builder:** Go to http://localhost:8080 and navigate to Forms Builder
143174
2. **Create/Edit Questionnaire:** Use the visual editor to build your form
144175
3. **Preview with Custom Renderer:** In the preview section, select your custom renderer from the dropdown
145176
4. **Test:** The preview will use your custom renderer instead of the default one
146177

178+
**Service URLs:**
179+
- Aidbox: http://localhost:8080
180+
- Custom renderer demo: http://localhost:8081
147181

148182
## Troubleshooting
149183

@@ -167,8 +201,7 @@ Create an initialization bundle to configure the custom renderer:
167201

168202
1. Check Aidbox logs: `docker-compose logs aidbox`
169203
2. Verify SDCConfig: `GET http://localhost:8080/SDCConfig/custom-renderer-config`
170-
3. Test renderer directly: http://localhost:8081/wrapped-questionnaire-renderer.js
204+
3. Test renderer directly: http://localhost:8081/simple-questionnaire-renderer.js
171205
4. Check browser console in Forms Builder for errors
172206

173-
174207
This example provides a complete foundation for integrating custom renderers that work seamlessly with the Aidbox Forms Builder.

aidbox-forms/aidbox-forms-builder-custom-renderer/docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ services:
6868
- "8081:80"
6969
volumes:
7070
- ./smartforms-component/dist/aidbox-forms-renderer-csiro-webcomponent.js:/srv/aidbox-forms-renderer-csiro-webcomponent.js
71+
- ./simple-questionnaire-renderer.js:/srv/simple-questionnaire-renderer.js
7172
depends_on:
7273
- aidbox
7374
healthcheck:
Lines changed: 64 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,68 @@
11
{
2-
"resourceType" : "Bundle",
3-
"type" : "transaction",
4-
"entry" : [ {
5-
"resource" : {
6-
"resourceType" : "SDCConfig",
7-
"name": "custom-renderers-config",
8-
"default": true,
9-
"id" : "custom-renderer-config",
10-
"builder": {
11-
"custom-renderers": [{
12-
"name" : "aidbox-form-csiro-renderer",
13-
"source" : "http://localhost:8081/aidbox-forms-renderer-csiro-webcomponent.js",
14-
"title" : "CSIRO"
15-
}]
2+
"resourceType": "Bundle",
3+
"type": "transaction",
4+
"entry": [
5+
{
6+
"resource": {
7+
"resourceType": "SDCConfig",
8+
"name": "custom-renderers-config",
9+
"default": true,
10+
"id": "custom-renderer-config",
11+
"builder": {
12+
"custom-renderers": [
13+
{
14+
"name": "aidbox-form-csiro-renderer",
15+
"source": "http://localhost:8081/aidbox-forms-renderer-csiro-webcomponent.js",
16+
"title": "CSIRO"
17+
},
18+
{
19+
"name": "simple-questionnaire-renderer",
20+
"source": "http://localhost:8081/simple-questionnaire-renderer.js",
21+
"title": "Simple Questionnaire Renderer"
22+
}
23+
]
24+
}
25+
},
26+
"request": {
27+
"method": "PUT",
28+
"url": "SDCConfig/custom-renderer-config"
1629
}
1730
},
18-
"request" : {
19-
"method" : "PUT",
20-
"url" : "SDCConfig/custom-renderer-config"
21-
}
22-
}, {
23-
"resource" : {
24-
"resourceType" : "Questionnaire",
25-
"id" : "sample-questionnaire",
26-
"url" : "http://example.org/questionnaire/sample",
27-
"title" : "Sample Patient Registration",
28-
"status" : "active",
29-
"item" : [ {
30-
"linkId" : "name",
31-
"type" : "string",
32-
"text" : "Full Name",
33-
"required" : true
34-
}, {
35-
"linkId" : "age",
36-
"type" : "integer",
37-
"text" : "Age"
38-
}, {
39-
"linkId" : "consent",
40-
"type" : "boolean",
41-
"text" : "I consent to treatment"
42-
}, {
43-
"linkId" : "email",
44-
"type" : "string",
45-
"text" : "Email Address"
46-
} ]
47-
},
48-
"request" : {
49-
"method" : "PUT",
50-
"url" : "/Questionnaire/sample-questionnaire"
31+
{
32+
"resource": {
33+
"resourceType": "Questionnaire",
34+
"id": "sample-questionnaire",
35+
"url": "http://example.org/questionnaire/sample",
36+
"title": "Sample Patient Registration",
37+
"status": "active",
38+
"item": [
39+
{
40+
"linkId": "name",
41+
"type": "string",
42+
"text": "Full Name",
43+
"required": true
44+
},
45+
{
46+
"linkId": "age",
47+
"type": "integer",
48+
"text": "Age"
49+
},
50+
{
51+
"linkId": "consent",
52+
"type": "boolean",
53+
"text": "I consent to treatment"
54+
},
55+
{
56+
"linkId": "email",
57+
"type": "string",
58+
"text": "Email Address"
59+
}
60+
]
61+
},
62+
"request": {
63+
"method": "PUT",
64+
"url": "/Questionnaire/sample-questionnaire"
65+
}
5166
}
52-
} ]
53-
}
67+
]
68+
}

aidbox-forms/aidbox-forms-builder-custom-renderer/smartforms-component/README.md

Lines changed: 0 additions & 19 deletions
This file was deleted.

aidbox-forms/aidbox-forms-builder-custom-renderer/smartforms-component/bun.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)