Skip to content

Commit 265db80

Browse files
authored
Merge pull request #1 from insistence/main
perf: update the example to demonstrate bidirectional control capability
2 parents 98e4bc8 + de53974 commit 265db80

3 files changed

Lines changed: 90 additions & 121 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,6 @@ cython_debug/
205205
marimo/_static/
206206
marimo/_lsp/
207207
__marimo__/
208+
209+
assets/
210+
_vite

example_react.py

Lines changed: 43 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,24 @@
1414
const App = () => {
1515
const [message, setMessage] = useState("Hello from React!");
1616
17+
const updateDash = () => {
18+
setMessage("Hello from React!");
19+
window.dash_clientside.set_props('dash-title', { children: 'Hello from React!' });
20+
};
21+
1722
const updateMessage = () => {
18-
setMessage("React is working!");
23+
setMessage("Hello from Dash!");
1924
};
2025
2126
return (
2227
<div id="react-app" style={{ margin: "20px" }}>
2328
<h1 style={{ color: "#42b883" }}>{message}</h1>
24-
<button onClick={updateMessage}>Click me!</button>
29+
<div>
30+
<button id="control-dash-button" onClick={updateDash}>Control Dash</button>
31+
</div>
32+
<div hidden>
33+
<button id="control-react-button" onClick={updateMessage}>Control Vue</button>
34+
</div>
2535
</div>
2636
);
2737
};
@@ -81,7 +91,8 @@
8191
NpmPackage('react'),
8292
NpmPackage('react-dom'),
8393
],
84-
clean_after=False,
94+
download_node=True,
95+
clean_after=True,
8596
)
8697

8798
# Call setup BEFORE creating Dash app (as required by the plugin architecture)
@@ -99,74 +110,46 @@
99110
html.H1('Vite Plugin Test - React Support', id='header'),
100111
html.P('This tests the Vite plugin with React support.', id='paragraph'),
101112
# Container for React app
102-
html.Div(id='react-container'),
103-
html.Div(id='react-out'),
104-
html.Div(id='js-test-result'),
105-
html.Button('Test JS', id='js-test-button', n_clicks=0),
106-
html.Button('Test React', id='react-test-button', n_clicks=0),
113+
html.Div(
114+
[
115+
'The content from React',
116+
html.Div(id='react-container'),
117+
]
118+
),
119+
html.Div(
120+
[
121+
'The content from Dash',
122+
html.Div(
123+
[html.H1('Hello from Dash!', id='dash-title'), html.Button('Control React', id='dash-button')],
124+
id='dash-app',
125+
style={'margin': '20px'},
126+
),
127+
],
128+
id='dash-container',
129+
),
107130
]
108131
)
109132

110-
# Add callback to test JavaScript execution
111-
app.clientside_callback(
112-
"""
113-
function(n_clicks) {
114-
if (n_clicks > 0) {
115-
// Test if global variable exists
116-
if (typeof window.testVariable !== 'undefined' && window.testVariable === 'VitePluginReactTest') {
117-
return 'JavaScript behavior is working correctly';
118-
} else {
119-
return 'Global variable test failed';
120-
}
121-
}
122-
return 'Click button to test JavaScript';
123-
}
124-
""",
125-
Output('js-test-result', 'children'),
126-
Input('js-test-button', 'n_clicks'),
127-
)
128133

129134
# Add callback to test React functionality with a simpler approach
130135
app.clientside_callback(
131136
"""
132-
async function(n_clicks) {
133-
function delay(ms) {
134-
return new Promise(resolve => setTimeout(resolve, ms));
135-
}
136-
async function testReactApp() {
137-
const reactApp = document.getElementById('react-app');
138-
if (reactApp) {
139-
const button = reactApp.querySelector('button');
140-
if (button) {
141-
const originalText = reactApp.querySelector('h1').textContent;
142-
button.click();
143-
await delay(0);
144-
const newText = reactApp.querySelector('h1').textContent;
145-
if (newText === 'React is working!') {
146-
return 'React is working correctly: ' + newText;
147-
} else {
148-
throw new Error('React button click failed. Original: ' + originalText + ', New: ' + newText);
149-
}
150-
} else {
151-
throw new Error('React button not found');
152-
}
153-
} else {
154-
throw new Error('React app not found');
155-
}
156-
}
157-
if (n_clicks > 0) {
158-
try {
159-
const result = await testReactApp();
160-
return result;
161-
} catch (error) {
162-
return error.message;
137+
function(n_clicks) {
138+
if (n_clicks > 0) {
139+
const reactApp = document.getElementById('react-app');
140+
if (reactApp) {
141+
const button = reactApp.querySelector('#control-react-button');
142+
if (button) {
143+
button.click();
144+
return 'Hello from Dash!';
163145
}
164146
}
165-
return 'Click button to test React';
147+
}
148+
return 'Hello from Dash!';
166149
}
167150
""",
168-
Output('react-out', 'children'),
169-
Input('react-test-button', 'n_clicks'),
151+
Output('dash-title', 'children'),
152+
Input('dash-button', 'n_clicks'),
170153
)
171154

172155

example_vue.py

Lines changed: 44 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212
f.write("""<template>
1313
<div id="vue-app">
1414
<h1>{{ message }}</h1>
15-
<button @click="updateMessage">Click me!</button>
15+
<div>
16+
<button id="control-dash-button" @click="updateDash">Control Dash</button>
17+
</div>
18+
<div hidden>
19+
<button id="control-vue-button" @click="updateMessage">Control Vue</button>
20+
</div>
1621
</div>
1722
</template>
1823
@@ -21,8 +26,13 @@
2126
2227
const message = ref("Hello from Vue!");
2328
29+
const updateDash = () => {
30+
message.value = "Hello from Vue!";
31+
window.dash_clientside.set_props('dash-title', { children: 'Hello from Vue!' });
32+
};
33+
2434
const updateMessage = () => {
25-
message.value = "Vue is working!";
35+
message.value = "Hello from Dash!";
2636
};
2737
</script>
2838
@@ -84,9 +94,10 @@
8494
build_assets_paths=['assets/js', 'assets/vue'],
8595
entry_js_paths=['assets/js/main.js'],
8696
npm_packages=[
87-
NpmPackage('vue'), # Removed version to use default/latest
97+
NpmPackage('vue'),
8898
],
89-
clean_after=False,
99+
download_node=True,
100+
clean_after=True,
90101
)
91102

92103
# Call setup BEFORE creating Dash app (as required by the plugin architecture)
@@ -104,74 +115,46 @@
104115
html.H1('Vite Plugin Test - Vue Support', id='header'),
105116
html.P('This tests the Vite plugin with Vue support.', id='paragraph'),
106117
# Container for Vue app
107-
html.Div(id='vue-container'),
108-
html.Div(id='vue-out'),
109-
html.Div(id='js-test-result'),
110-
html.Button('Test JS', id='js-test-button', n_clicks=0),
111-
html.Button('Test Vue', id='vue-test-button', n_clicks=0),
118+
html.Div(
119+
[
120+
'The content from Vue',
121+
html.Div(id='vue-container'),
122+
]
123+
),
124+
html.Div(
125+
[
126+
'The content from Dash',
127+
html.Div(
128+
[html.H1('Hello from Dash!', id='dash-title'), html.Button('Control Vue', id='dash-button')],
129+
id='dash-app',
130+
style={'margin': '20px'},
131+
),
132+
],
133+
id='dash-container',
134+
),
112135
]
113136
)
114137

115-
# Add callback to test JavaScript execution
116-
app.clientside_callback(
117-
"""
118-
function(n_clicks) {
119-
if (n_clicks > 0) {
120-
// Test if global variable exists
121-
if (typeof window.testVariable !== 'undefined' && window.testVariable === 'VitePluginVueTest') {
122-
return 'JavaScript behavior is working correctly';
123-
} else {
124-
return 'Global variable test failed';
125-
}
126-
}
127-
return 'Click button to test JavaScript';
128-
}
129-
""",
130-
Output('js-test-result', 'children'),
131-
Input('js-test-button', 'n_clicks'),
132-
)
133138

134139
# Add callback to test Vue functionality with a simpler approach
135140
app.clientside_callback(
136141
"""
137-
async function(n_clicks) {
138-
function delay(ms) {
139-
return new Promise(resolve => setTimeout(resolve, ms));
140-
}
141-
async function testVueApp() {
142-
const vueApp = document.getElementById('vue-app');
143-
if (vueApp) {
144-
const button = vueApp.querySelector('button');
145-
if (button) {
146-
const originalText = vueApp.querySelector('h1').textContent;
147-
button.click();
148-
await delay(0);
149-
const newText = vueApp.querySelector('h1').textContent;
150-
if (newText === 'Vue is working!') {
151-
return 'Vue is working correctly: ' + newText;
152-
} else {
153-
throw new Error('Vue button click failed. Original: ' + originalText + ', New: ' + newText);
154-
}
155-
} else {
156-
throw new Error('Vue button not found');
157-
}
158-
} else {
159-
throw new Error('Vue app not found');
160-
}
161-
}
162-
if (n_clicks > 0) {
163-
try {
164-
const result = await testVueApp();
165-
return result;
166-
} catch (error) {
167-
return error.message;
142+
function(n_clicks) {
143+
if (n_clicks > 0) {
144+
const vueApp = document.getElementById('vue-app');
145+
if (vueApp) {
146+
const button = vueApp.querySelector('#control-vue-button');
147+
if (button) {
148+
button.click();
149+
return 'Hello from Dash!';
168150
}
169151
}
170-
return 'Click button to test Vue';
152+
}
153+
return 'Hello from Dash!';
171154
}
172155
""",
173-
Output('vue-out', 'children'),
174-
Input('vue-test-button', 'n_clicks'),
156+
Output('dash-title', 'children'),
157+
Input('dash-button', 'n_clicks'),
175158
)
176159

177160

0 commit comments

Comments
 (0)