Skip to content

Commit fda5b1e

Browse files
Rough sketch of form post progressive enhancement. Will probably break other form uses though. (#15)
1 parent ed330ff commit fda5b1e

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

src/Components/Samples/BlazorUnitedApp/Pages/CounterPassive.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<p>Current count: @CurrentCount</p>
88

9-
<form method="post">
9+
<form method="post" enhance>
1010
<input name="@nameof(CurrentCount)" type="hidden" value="@CurrentCount" />
1111

1212
<ActionButton Name="inc" OnClick="@(() => ChangeCount(1))" class="btn btn-primary" disabled="@inProgress">

src/Components/Web.JS/src/Boot.United.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { startCircuit } from './Boot.Server.Common';
88
import { AutoComponentDescriptor, discoverComponents, ServerComponentDescriptor, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
99
import { beginLoadingDotNetRuntime, loadBootConfig, startWebAssembly } from './Boot.WebAssembly.Common';
1010
import { loadWebAssemblyResources } from './Platform/Mono/MonoPlatform';
11+
import { enableFormEnhancement } from './FormEnhancement';
1112

1213
let started = false;
1314

@@ -71,3 +72,5 @@ if (shouldAutoStart()) {
7172
};
7273
document.addEventListener('readystatechange', onReadyStateChange);
7374
}
75+
76+
enableFormEnhancement();
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
export function enableFormEnhancement() {
2+
document.body.addEventListener('submit', async evt => {
3+
const form = evt.target as HTMLFormElement;
4+
if (!form || form.getAttribute('enhance') === null) {
5+
return;
6+
}
7+
8+
evt.preventDefault();
9+
10+
const url = new URL(form.action);
11+
const fetchOptions: RequestInit = { method: form.method };
12+
const formData = new FormData(form);
13+
const submitter = evt.submitter as HTMLButtonElement;
14+
if (submitter && submitter.name) {
15+
formData.append(submitter.name, submitter.value);
16+
}
17+
if (fetchOptions.method === 'get') {
18+
(url as any).search = new URLSearchParams(formData as any);
19+
} else {
20+
fetchOptions.body = formData;
21+
}
22+
23+
const response = await fetch(url, fetchOptions);
24+
const responseReader = response.body!.getReader();
25+
const decoder = new TextDecoder();
26+
let responseHtml = '';
27+
let finished = false;
28+
29+
while (!finished) {
30+
const chunk = await responseReader.read();
31+
if (chunk.done) {
32+
finished = true;
33+
}
34+
35+
if (chunk.value) {
36+
const chunkText = decoder.decode(chunk.value);
37+
responseHtml += chunkText;
38+
39+
// This is obviously not robust. Maybe we can rely on the initial HTML always being in the first chunk.
40+
if (chunkText.indexOf('</html>') > 0) {
41+
break;
42+
}
43+
}
44+
}
45+
46+
const parsedHtml = new DOMParser().parseFromString(responseHtml, 'text/html');
47+
document.body.innerHTML = parsedHtml.body.innerHTML;
48+
responseHtml = '';
49+
50+
while (!finished) {
51+
const chunk = await responseReader.read();
52+
if (chunk.done) {
53+
finished = true;
54+
}
55+
56+
if (chunk.value) {
57+
const chunkText = decoder.decode(chunk.value);
58+
responseHtml += chunkText;
59+
60+
// Not making any attempt to cope if the chunk boundaries don't line up with the script blocks
61+
if (chunkText.indexOf('</script>') > 0) {
62+
const parsedHtml = new DOMParser().parseFromString(responseHtml, 'text/html');
63+
for (let i = 0; i < parsedHtml.scripts.length; i++) {
64+
const script = parsedHtml.scripts[i];
65+
if (script.textContent) {
66+
eval(script.textContent);
67+
}
68+
}
69+
responseHtml = '';
70+
}
71+
}
72+
}
73+
});
74+
}

0 commit comments

Comments
 (0)