Skip to content

Commit 3370bef

Browse files
committed
feat: add an angular-21 app demo
1 parent da07ea8 commit 3370bef

3 files changed

Lines changed: 151 additions & 0 deletions

File tree

angular-21/deno.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"imports": {
3+
"@angular/common": "https://esm.sh/*@angular/common@21.0.0-rc.0?dev",
4+
"@angular/common/": "https://esm.sh/*@angular/common@21.0.0-rc.0&dev/",
5+
"@angular/compiler": "https://esm.sh/*@angular/compiler@21.0.0-rc.0?dev",
6+
"@angular/core": "https://esm.sh/*@angular/core@21.0.0-rc.0?dev",
7+
"@angular/core/": "https://esm.sh/*@angular/core@21.0.0-rc.0&dev/",
8+
"@angular/forms": "https://esm.sh/*@angular/forms@21.0.0-rc.0?dev",
9+
"@angular/forms/": "https://esm.sh/*@angular/forms@21.0.0-rc.0&dev/",
10+
"@angular/platform-browser": "https://esm.sh/*@angular/platform-browser@21.0.0-rc.0?dev",
11+
"@angular/platform-browser/": "https://esm.sh/*@angular/platform-browser@21.0.0-rc.0&dev/",
12+
"rxjs": "https://esm.sh/*rxjs@^7.4.0?dev",
13+
"rxjs/": "https://esm.sh/*rxjs@^7.4.0&dev/",
14+
"tslib": "https://esm.sh/*tslib@^2.3.0?dev"
15+
}
16+
}

angular-21/index.html

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Buildless Angular 21 app</title>
6+
<script type="importmap">
7+
{
8+
"imports": {
9+
"@angular/common": "https://esm.sh/*@angular/common@21.0.0-rc.0?dev",
10+
"@angular/common/": "https://esm.sh/*@angular/common@21.0.0-rc.0&dev/",
11+
"@angular/compiler": "https://esm.sh/*@angular/compiler@21.0.0-rc.0?dev",
12+
"@angular/core": "https://esm.sh/*@angular/core@21.0.0-rc.0?dev",
13+
"@angular/core/": "https://esm.sh/*@angular/core@21.0.0-rc.0&dev/",
14+
"@angular/forms": "https://esm.sh/*@angular/forms@21.0.0-rc.0?dev",
15+
"@angular/forms/": "https://esm.sh/*@angular/forms@21.0.0-rc.0&dev/",
16+
"@angular/platform-browser": "https://esm.sh/*@angular/platform-browser@21.0.0-rc.0?dev",
17+
"@angular/platform-browser/": "https://esm.sh/*@angular/platform-browser@21.0.0-rc.0&dev/",
18+
"rxjs": "https://esm.sh/*rxjs@^7.4.0?dev",
19+
"rxjs/": "https://esm.sh/*rxjs@^7.4.0&dev/",
20+
"tslib": "https://esm.sh/*tslib@^2.3.0?dev"
21+
}
22+
}
23+
</script>
24+
<script type="module">
25+
import {
26+
availablePlugins,
27+
availablePresets,
28+
registerPreset,
29+
} from "https://esm.sh/@babel/standalone@7.28.1";
30+
31+
registerPreset("angular", {
32+
presets: [[availablePresets["typescript"]]],
33+
plugins: [
34+
[availablePlugins["proposal-decorators"], { version: "legacy" }],
35+
[availablePlugins["transform-class-properties"]],
36+
],
37+
});
38+
</script>
39+
<!-- `data-plugins=""` attribute is required for @babel/standalone@7.28.1 -->
40+
<script
41+
type="text/babel"
42+
data-presets="angular"
43+
data-plugins=""
44+
data-type="module"
45+
src="./main.ts"
46+
></script>
47+
</head>
48+
<body>
49+
<app-root></app-root>
50+
</body>
51+
</html>

angular-21/main.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import "@angular/compiler";
2+
3+
import { TitleCasePipe } from "@angular/common";
4+
import { httpResource } from "@angular/common/http";
5+
import {
6+
Component,
7+
computed,
8+
inject,
9+
Injectable,
10+
type Signal,
11+
signal,
12+
} from "@angular/core";
13+
import { Field, form } from "@angular/forms/signals";
14+
import { bootstrapApplication } from "@angular/platform-browser";
15+
16+
@Injectable({ providedIn: "root" })
17+
class AppService {
18+
static readonly #urlBase = "https://jsonplaceholder.typicode.com";
19+
20+
getUsers() {
21+
return httpResource(() => `${AppService.#urlBase}/users`);
22+
}
23+
24+
getPosts(userIdSignal: Signal<string | undefined>) {
25+
return httpResource(() => {
26+
const userId = userIdSignal();
27+
if (userId == undefined) return undefined;
28+
return {
29+
url: `${AppService.#urlBase}/posts`,
30+
params: { userId },
31+
};
32+
});
33+
}
34+
}
35+
36+
@Component({
37+
selector: "app-root",
38+
imports: [Field, TitleCasePipe],
39+
template: `
40+
<h1>Buildless Angular 21 app</h1>
41+
@if (users.hasValue()) {
42+
<label>
43+
Select User:
44+
<select [field]="form.selectedUserId">
45+
@for (user of users.value(); track user.id) {
46+
<option value="{{ user.id }}">
47+
&#64;{{ user.username }}: {{ user.name }}
48+
</option>
49+
}
50+
</select>
51+
</label>
52+
} @else if (users.isLoading()) {
53+
<p>Loading Users...</p>
54+
}
55+
@if (posts.hasValue()) {
56+
<ul>
57+
@for (post of posts.value(); track post.id) {
58+
<li>{{ post.title | titlecase }}</li>
59+
}
60+
</ul>
61+
} @else if (posts.isLoading()) {
62+
<p>Loading Posts...</p>
63+
} @else if (users.hasValue()) {
64+
<p>Select User to view posts</p>
65+
}
66+
<p>
67+
Data Source:
68+
<a href="https://jsonplaceholder.typicode.com/" target="_blank">
69+
JSONPlaceholder
70+
</a>
71+
</p>
72+
`,
73+
})
74+
class App {
75+
readonly #formState = signal({ selectedUserId: "" });
76+
77+
protected readonly form = form(this.#formState);
78+
protected readonly users = inject(AppService).getUsers();
79+
protected readonly posts = inject(AppService).getPosts(
80+
computed(() => this.#formState().selectedUserId || undefined),
81+
);
82+
}
83+
84+
await bootstrapApplication(App);

0 commit comments

Comments
 (0)