Skip to content

Commit 62f94fc

Browse files
committed
fix(router): properly parse json response in the FormAction
1 parent b104183 commit 62f94fc

File tree

5 files changed

+62
-25
lines changed

5 files changed

+62
-25
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as newsletter from '../support/newsletter.po';
2+
3+
describe('Newsletter', () => {
4+
it(`Given the user has filled in their email
5+
When the "Submit" button is clicked
6+
Then the user has sign up for the newsletter`, () => {
7+
const email = '[email protected]';
8+
cy.visit('/newsletter');
9+
newsletter.typeEmail(email);
10+
11+
newsletter.submit();
12+
newsletter
13+
.getSubmitMessage()
14+
.should('contain.text', `Thanks for signing up, ${email}!`);
15+
});
16+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const typeEmail = (email: string) =>
2+
cy.get('input[name="email"]').type(email);
3+
4+
export const submit = () => cy.contains('button', /submit/i).click();
5+
6+
export const getSubmitMessage = () => cy.get('#signup-message');

apps/analog-app/src/app/pages/newsletter.page.ts

+26-21
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Component, signal } from '@angular/core';
22

33
import { FormAction } from '@analogjs/router';
44

5+
import { type NewsletterSubmitResponse } from './newsletter.server';
6+
57
type FormErrors =
68
| {
79
email?: string;
@@ -15,34 +17,37 @@ type FormErrors =
1517
template: `
1618
<h3>Newsletter Signup</h3>
1719
18-
@if (!signedUp()) {
19-
<form
20-
method="post"
21-
(onSuccess)="onSuccess()"
22-
(onError)="onError($any($event))"
23-
(onStateChange)="errors.set(undefined)"
24-
>
25-
<div>
26-
<label for="email"> Email </label>
27-
<input type="email" name="email" />
20+
@if (signedUpEmail()) {
21+
<div id="signup-message">
22+
Thanks for signing up, {{ signedUpEmail() }}!
2823
</div>
29-
30-
<button class="button" type="submit">Submit</button>
31-
</form>
32-
33-
@if (errors()?.email) {
34-
<p>{{ errors()?.email }}</p>
35-
} } @else {
36-
<div>Thanks for signing up!</div>
24+
} @else {
25+
<form
26+
method="post"
27+
(onSuccess)="onSuccess($any($event))"
28+
(onError)="onError($any($event))"
29+
(onStateChange)="errors.set(undefined)"
30+
>
31+
<div>
32+
<label for="email"> Email </label>
33+
<input type="email" name="email" />
34+
</div>
35+
36+
<button class="button" type="submit">Submit</button>
37+
</form>
38+
39+
@if (errors()?.email) {
40+
<p>{{ errors()?.email }}</p>
41+
}
3742
}
3843
`,
3944
})
4045
export default class NewsletterComponent {
41-
signedUp = signal(false);
46+
signedUpEmail = signal('');
4247
errors = signal<FormErrors>(undefined);
4348

44-
onSuccess() {
45-
this.signedUp.set(true);
49+
onSuccess(res: NewsletterSubmitResponse) {
50+
this.signedUpEmail.set(res.email);
4651
}
4752

4853
onError(result?: FormErrors) {

apps/analog-app/src/app/pages/newsletter.server.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import {
66
} from '@analogjs/router/server/actions';
77
import { readFormData } from 'h3';
88

9+
export type NewsletterSubmitResponse = {
10+
type: 'success';
11+
email: string;
12+
};
13+
914
export function load() {
1015
return {
1116
loaded: true,
@@ -24,7 +29,5 @@ export async function action({ event }: PageServerAction) {
2429
return redirect('/');
2530
}
2631

27-
console.log({ email: body.get('email') });
28-
29-
return json({ type: 'success' });
32+
return json<NewsletterSubmitResponse>({ type: 'success', email });
3033
}

packages/router/src/lib/form-action.directive.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class FormAction {
6161
const redirectUrl = new URL(res.url).pathname;
6262
this.state.emit('redirect');
6363
this.router.navigate([redirectUrl]);
64-
} else if (res.headers.get('Content-type') === 'application/json') {
64+
} else if (this._isJSON(res.headers.get('Content-type'))) {
6565
res.json().then((result) => {
6666
this.onSuccess.emit(result);
6767
this.state.emit('success');
@@ -95,4 +95,11 @@ export class FormAction {
9595

9696
return `/api/_analog/pages${window.location.pathname}`;
9797
}
98+
99+
private _isJSON(contentType: string | null): boolean {
100+
const mime = contentType ? contentType.split(';') : [];
101+
const essence = mime[0];
102+
103+
return essence === 'application/json';
104+
}
98105
}

0 commit comments

Comments
 (0)