diff --git a/README.md b/README.md
index d5bd3ce1..1c8dbf1f 100644
--- a/README.md
+++ b/README.md
@@ -127,7 +127,7 @@ How do we solve this ? Developers love having framework overview by examples. It
Angular
-
+
- [x] Reactivity
- [x] Declare state
@@ -143,12 +143,12 @@ How do we solve this ? Developers love having framework overview by examples. It
- [x] Lifecycle
- [x] On mount
- [x] On unmount
-- [ ] Component composition
+- [x] Component composition
- [x] Props
- [x] Emit to parent
- [x] Slot
- [x] Slot fallback
- - [ ] Context
+ - [x] Context
- [x] Form input
- [x] Input text
- [x] Checkbox
@@ -550,7 +550,7 @@ How do we solve this ? Developers love having framework overview by examples. It
- [x] Lifecycle
- [x] On mount
- [x] On unmount
-- [ ] Component composition
+- [x] Component composition
- [x] Props
- [x] Emit to parent
- [x] Slot
@@ -604,6 +604,43 @@ How do we solve this ? Developers love having framework overview by examples. It
- [x] Router link
- [x] Routing
+
+
+
+ Angular "Renaissance" (v14+)
+
+
+- [x] Reactivity
+ - [x] Declare state
+ - [x] Update state
+ - [x] Computed state
+- [x] Templating
+ - [x] Minimal template
+ - [x] Styling
+ - [x] Loop
+ - [x] Event click
+ - [x] Dom ref
+ - [x] Conditional
+- [x] Lifecycle
+ - [x] On mount
+ - [x] On unmount
+- [x] Component composition
+ - [x] Props
+ - [x] Emit to parent
+ - [x] Slot
+ - [x] Slot fallback
+ - [x] Context
+- [x] Form input
+ - [x] Input text
+ - [x] Checkbox
+ - [x] Radio
+ - [x] Select
+- [x] Webapp features
+ - [x] Render app
+ - [x] Fetch data
+ - [x] Router link
+ - [x] Routing
+
diff --git a/content/1-reactivity/1-declare-state/angular-renaissance/name.component.ts b/content/1-reactivity/1-declare-state/angular-renaissance/name.component.ts
new file mode 100644
index 00000000..e756e958
--- /dev/null
+++ b/content/1-reactivity/1-declare-state/angular-renaissance/name.component.ts
@@ -0,0 +1,10 @@
+import { Component, signal } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-name",
+ template: `
Hello {{ name() }}
`,
+})
+export class NameComponent {
+ name = signal("John");
+}
diff --git a/content/1-reactivity/1-declare-state/angular/name.component.ts b/content/1-reactivity/1-declare-state/angular/name.component.ts
index 8e5eb9b8..7baf4ff7 100644
--- a/content/1-reactivity/1-declare-state/angular/name.component.ts
+++ b/content/1-reactivity/1-declare-state/angular/name.component.ts
@@ -1,4 +1,4 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
@Component({
selector: "app-name",
@@ -7,3 +7,9 @@ import { Component } from "@angular/core";
export class NameComponent {
name = "John";
}
+
+@NgModule({
+ declarations: [NameComponent],
+ exports: [NameComponent],
+})
+export class NameModule {}
diff --git a/content/1-reactivity/2-update-state/angular-renaissance/name.component.ts b/content/1-reactivity/2-update-state/angular-renaissance/name.component.ts
new file mode 100644
index 00000000..3d0f2ff9
--- /dev/null
+++ b/content/1-reactivity/2-update-state/angular-renaissance/name.component.ts
@@ -0,0 +1,14 @@
+import { Component, signal } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-name",
+ template: `Hello {{ name() }}
`,
+})
+export class NameComponent {
+ name = signal("John");
+
+ constructor() {
+ this.name.set("Jane");
+ }
+}
diff --git a/content/1-reactivity/2-update-state/angular/name.component.ts b/content/1-reactivity/2-update-state/angular/name.component.ts
index 58bcb040..c68cc0eb 100644
--- a/content/1-reactivity/2-update-state/angular/name.component.ts
+++ b/content/1-reactivity/2-update-state/angular/name.component.ts
@@ -1,4 +1,4 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
@Component({
selector: "app-name",
@@ -11,3 +11,9 @@ export class NameComponent {
this.name = "Jane";
}
}
+
+@NgModule({
+ declarations: [NameComponent],
+ exports: [NameComponent],
+})
+export class NameModule {}
diff --git a/content/1-reactivity/3-computed-state/angular-renaissance/doublecount.component.ts b/content/1-reactivity/3-computed-state/angular-renaissance/doublecount.component.ts
new file mode 100644
index 00000000..f14d7270
--- /dev/null
+++ b/content/1-reactivity/3-computed-state/angular-renaissance/doublecount.component.ts
@@ -0,0 +1,12 @@
+import { Component, computed, signal } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-doublecount",
+ template: `{{ doubleCount() }}
`,
+})
+export class DoublecountComponent {
+ count = signal(10);
+
+ doubleCount = computed(() => this.count() * 2);
+}
diff --git a/content/1-reactivity/3-computed-state/angular/doublecount.component.ts b/content/1-reactivity/3-computed-state/angular/doublecount.component.ts
index 423413cb..165d1349 100644
--- a/content/1-reactivity/3-computed-state/angular/doublecount.component.ts
+++ b/content/1-reactivity/3-computed-state/angular/doublecount.component.ts
@@ -1,4 +1,4 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
@Component({
selector: "app-doublecount",
@@ -11,3 +11,9 @@ export class DoublecountComponent {
return this.count * 2;
}
}
+
+@NgModule({
+ declarations: [DoublecountComponent],
+ exports: [DoublecountComponent],
+})
+export class DoublecountModule {}
diff --git a/content/2-templating/1-minimal-template/angular-renaissance/helloworld.component.ts b/content/2-templating/1-minimal-template/angular-renaissance/helloworld.component.ts
new file mode 100644
index 00000000..be38ebd4
--- /dev/null
+++ b/content/2-templating/1-minimal-template/angular-renaissance/helloworld.component.ts
@@ -0,0 +1,8 @@
+import { Component } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-helloworld",
+ template: `Hello world
`,
+})
+export class HelloworldComponent {}
diff --git a/content/2-templating/1-minimal-template/angular/helloworld.component.ts b/content/2-templating/1-minimal-template/angular/helloworld.component.ts
index adf68d5b..f4f6326b 100644
--- a/content/2-templating/1-minimal-template/angular/helloworld.component.ts
+++ b/content/2-templating/1-minimal-template/angular/helloworld.component.ts
@@ -1,7 +1,13 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
@Component({
selector: "app-helloworld",
template: `Hello world
`,
})
export class HelloworldComponent {}
+
+@NgModule({
+ declarations: [HelloworldComponent],
+ exports: [HelloworldComponent],
+})
+export class HelloworldModule {}
diff --git a/content/2-templating/2-styling/angular-renaissance/cssstyle.component.ts b/content/2-templating/2-styling/angular-renaissance/cssstyle.component.ts
new file mode 100644
index 00000000..bb81145a
--- /dev/null
+++ b/content/2-templating/2-styling/angular-renaissance/cssstyle.component.ts
@@ -0,0 +1,16 @@
+import { Component } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-cssstyle",
+ template: `
+ I am red
+
+ `,
+ styles: `
+ .title {
+ color: red;
+ }
+ `,
+})
+export class CssStyleComponent {}
diff --git a/content/2-templating/2-styling/angular/cssstyle.component.ts b/content/2-templating/2-styling/angular/cssstyle.component.ts
index 98df5ea6..4bacab3c 100644
--- a/content/2-templating/2-styling/angular/cssstyle.component.ts
+++ b/content/2-templating/2-styling/angular/cssstyle.component.ts
@@ -1,4 +1,4 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
@Component({
selector: "app-cssstyle",
@@ -15,3 +15,9 @@ import { Component } from "@angular/core";
],
})
export class CssStyleComponent {}
+
+@NgModule({
+ declarations: [CssStyleComponent],
+ exports: [CssStyleComponent],
+})
+export class CssStyleModule {}
diff --git a/content/2-templating/3-loop/angular-renaissance/colors.component.ts b/content/2-templating/3-loop/angular-renaissance/colors.component.ts
new file mode 100644
index 00000000..5e210a52
--- /dev/null
+++ b/content/2-templating/3-loop/angular-renaissance/colors.component.ts
@@ -0,0 +1,16 @@
+import { Component } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-colors",
+ template: `
+
+ @for (color of colors; track color) {
+ - {{ color }}
+ }
+
+ `,
+})
+export class ColorsComponent {
+ colors = ["red", "green", "blue"];
+}
diff --git a/content/2-templating/3-loop/angular/colors.component.ts b/content/2-templating/3-loop/angular/colors.component.ts
index ec438d37..716d9575 100644
--- a/content/2-templating/3-loop/angular/colors.component.ts
+++ b/content/2-templating/3-loop/angular/colors.component.ts
@@ -1,4 +1,5 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
+import { CommonModule } from "@angular/common";
@Component({
selector: "app-colors",
@@ -11,3 +12,10 @@ import { Component } from "@angular/core";
export class ColorsComponent {
colors = ["red", "green", "blue"];
}
+
+@NgModule({
+ declarations: [ColorsComponent],
+ imports: [CommonModule],
+ exports: [ColorsComponent],
+})
+export class ColorsModule {}
diff --git a/content/2-templating/4-event-click/angular-renaissance/counter.component.ts b/content/2-templating/4-event-click/angular-renaissance/counter.component.ts
new file mode 100644
index 00000000..d3b77d7e
--- /dev/null
+++ b/content/2-templating/4-event-click/angular-renaissance/counter.component.ts
@@ -0,0 +1,17 @@
+import { Component, signal } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-counter",
+ template: `
+ Counter: {{ count() }}
+
+ `,
+})
+export class CounterComponent {
+ count = signal(0);
+
+ incrementCount() {
+ this.count.update((count) => count + 1);
+ }
+}
diff --git a/content/2-templating/4-event-click/angular/counter.component.ts b/content/2-templating/4-event-click/angular/counter.component.ts
index 298a2d29..3593fd8d 100644
--- a/content/2-templating/4-event-click/angular/counter.component.ts
+++ b/content/2-templating/4-event-click/angular/counter.component.ts
@@ -1,4 +1,4 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
@Component({
selector: "app-counter",
@@ -14,3 +14,9 @@ export class CounterComponent {
this.count++;
}
}
+
+@NgModule({
+ declarations: [CounterComponent],
+ exports: [CounterComponent],
+})
+export class CounterModule {}
diff --git a/content/2-templating/5-dom-ref/angular-renaissance/inputfocused.component.ts b/content/2-templating/5-dom-ref/angular-renaissance/inputfocused.component.ts
new file mode 100644
index 00000000..689bcdb2
--- /dev/null
+++ b/content/2-templating/5-dom-ref/angular-renaissance/inputfocused.component.ts
@@ -0,0 +1,14 @@
+import { Component, ElementRef, OnInit, viewChild } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-inputfocused",
+ template: ``,
+})
+export class InputfocusedComponent implements OnInit {
+ inputRef = viewChild.required>("inputRef");
+
+ ngOnInit() {
+ this.inputRef().nativeElement.focus();
+ }
+}
diff --git a/content/2-templating/5-dom-ref/angular/inputfocused.component.ts b/content/2-templating/5-dom-ref/angular/inputfocused.component.ts
index b7354db0..4c1843d4 100644
--- a/content/2-templating/5-dom-ref/angular/inputfocused.component.ts
+++ b/content/2-templating/5-dom-ref/angular/inputfocused.component.ts
@@ -1,4 +1,10 @@
-import { Component, ViewChild, ElementRef, OnInit } from "@angular/core";
+import {
+ Component,
+ ViewChild,
+ ElementRef,
+ OnInit,
+ NgModule,
+} from "@angular/core";
@Component({
selector: "app-inputfocused",
@@ -12,3 +18,9 @@ export class InputfocusedComponent implements OnInit {
this.inputRef.nativeElement.focus();
}
}
+
+@NgModule({
+ declarations: [InputfocusedComponent],
+ exports: [InputfocusedComponent],
+})
+export class InputfocusedModule {}
diff --git a/content/2-templating/6-conditional/angular-renaissance/trafficlight.component.ts b/content/2-templating/6-conditional/angular-renaissance/trafficlight.component.ts
new file mode 100644
index 00000000..3f87a870
--- /dev/null
+++ b/content/2-templating/6-conditional/angular-renaissance/trafficlight.component.ts
@@ -0,0 +1,35 @@
+import { Component, computed, signal } from "@angular/core";
+
+const TRAFFIC_LIGHTS = ["red", "orange", "green"];
+
+@Component({
+ standalone: true,
+ selector: "app-trafficlight",
+ template: `
+
+ Light is: {{ light() }}
+
+ You must
+ @switch (light()) {
+ @case ("red") {
+ STOP
+ }
+ @case ("orange") {
+ SLOW DOWN
+ }
+ @case ("green") {
+ GO
+ }
+ }
+
+ `,
+})
+export class TrafficlightComponent {
+ lightIndex = signal(0);
+
+ light = computed(() => TRAFFIC_LIGHTS[this.lightIndex()]);
+
+ nextLight() {
+ this.lightIndex.update((index) => (index + 1) % TRAFFIC_LIGHTS.length);
+ }
+}
diff --git a/content/2-templating/6-conditional/angular/trafficlight.component.ts b/content/2-templating/6-conditional/angular/trafficlight.component.ts
index 4235ad45..5611d5df 100644
--- a/content/2-templating/6-conditional/angular/trafficlight.component.ts
+++ b/content/2-templating/6-conditional/angular/trafficlight.component.ts
@@ -1,4 +1,5 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
+import { CommonModule } from "@angular/common";
const TRAFFIC_LIGHTS = ["red", "orange", "green"];
@@ -28,3 +29,10 @@ export class TrafficlightComponent {
this.lightIndex = (this.lightIndex + 1) % TRAFFIC_LIGHTS.length;
}
}
+
+@NgModule({
+ declarations: [TrafficlightComponent],
+ imports: [CommonModule],
+ exports: [TrafficlightComponent],
+})
+export class TrafficlightModule {}
diff --git a/content/3-lifecycle/1-on-mount/angular-renaissance/pagetitle.component.ts b/content/3-lifecycle/1-on-mount/angular-renaissance/pagetitle.component.ts
new file mode 100644
index 00000000..06ddfa2b
--- /dev/null
+++ b/content/3-lifecycle/1-on-mount/angular-renaissance/pagetitle.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-pagetitle",
+ template: `Page title: {{ pageTitle }}
`,
+})
+export class PagetitleComponent implements OnInit {
+ pageTitle = "";
+
+ ngOnInit() {
+ this.pageTitle = document.title;
+ }
+}
diff --git a/content/3-lifecycle/1-on-mount/angular/pagetitle.component.ts b/content/3-lifecycle/1-on-mount/angular/pagetitle.component.ts
index 04c2b1eb..f0c39643 100644
--- a/content/3-lifecycle/1-on-mount/angular/pagetitle.component.ts
+++ b/content/3-lifecycle/1-on-mount/angular/pagetitle.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from "@angular/core";
+import { Component, NgModule, OnInit } from "@angular/core";
@Component({
selector: "app-pagetitle",
@@ -11,3 +11,9 @@ export class PagetitleComponent implements OnInit {
this.pageTitle = document.title;
}
}
+
+@NgModule({
+ declarations: [PagetitleComponent],
+ exports: [PagetitleComponent],
+})
+export class PagetitleModule {}
diff --git a/content/3-lifecycle/2-on-unmount/angular-renaissance/time.component.ts b/content/3-lifecycle/2-on-unmount/angular-renaissance/time.component.ts
new file mode 100644
index 00000000..fbc3da5c
--- /dev/null
+++ b/content/3-lifecycle/2-on-unmount/angular-renaissance/time.component.ts
@@ -0,0 +1,33 @@
+import { Component, OnDestroy, signal } from "@angular/core";
+
+/* FIXME with rxjs + toSignal (but no need for onDestroy anymore)
+```ts
+@Component({
+ standalone: true,
+ selector: "app-time",
+ template: `Current time: {{ time() }}
`,
+})
+export class TimeComponent {
+ time = toSignal(timer(0, 1000).pipe(
+ map(() => new Date().toLocaleTimeString()),
+ ));
+}
+```
+*/
+@Component({
+ standalone: true,
+ selector: "app-time",
+ template: `Current time: {{ time() }}
`,
+})
+export class TimeComponent implements OnDestroy {
+ time = signal(new Date().toLocaleTimeString());
+
+ timer = setInterval(
+ () => this.time.set(new Date().toLocaleTimeString()),
+ 1000
+ );
+
+ ngOnDestroy() {
+ clearInterval(this.timer);
+ }
+}
diff --git a/content/3-lifecycle/2-on-unmount/angular/time.component.ts b/content/3-lifecycle/2-on-unmount/angular/time.component.ts
index 8f9b3c02..715c8ece 100644
--- a/content/3-lifecycle/2-on-unmount/angular/time.component.ts
+++ b/content/3-lifecycle/2-on-unmount/angular/time.component.ts
@@ -1,20 +1,23 @@
-import { Component, OnDestroy } from "@angular/core";
+import { Component, NgModule, OnDestroy } from "@angular/core";
@Component({
selector: "app-time",
template: `Current time: {{ time }}
`,
})
export class TimeComponent implements OnDestroy {
- time: string = new Date().toLocaleTimeString();
- timer: number;
+ time = new Date().toLocaleTimeString();
- constructor() {
- this.timer = setInterval(() => {
- this.time = new Date().toLocaleTimeString();
- }, 1000);
- }
+ timer = setInterval(() => {
+ this.time = new Date().toLocaleTimeString();
+ }, 1000);
ngOnDestroy() {
clearInterval(this.timer);
}
}
+
+@NgModule({
+ declarations: [TimeComponent],
+ exports: [TimeComponent],
+})
+export class TimeModule {}
diff --git a/content/4-component-composition/1-props/angular-renaissance/app.component.ts b/content/4-component-composition/1-props/angular-renaissance/app.component.ts
new file mode 100644
index 00000000..436bafde
--- /dev/null
+++ b/content/4-component-composition/1-props/angular-renaissance/app.component.ts
@@ -0,0 +1,17 @@
+import { Component } from "@angular/core";
+import { UserprofileComponent } from "./userprofile.component";
+
+@Component({
+ standalone: true,
+ selector: "app-root",
+ imports: [UserprofileComponent],
+ template: `
+
+ `,
+})
+export class AppComponent {}
diff --git a/content/4-component-composition/1-props/angular-renaissance/userprofile.component.ts b/content/4-component-composition/1-props/angular-renaissance/userprofile.component.ts
new file mode 100644
index 00000000..e775f32e
--- /dev/null
+++ b/content/4-component-composition/1-props/angular-renaissance/userprofile.component.ts
@@ -0,0 +1,18 @@
+import { Component, input } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-userprofile",
+ template: `
+ My name is {{ name() }}!
+ My age is {{ age() }}!
+ My favourite colors are {{ favouriteColors().join(", ") }}!
+ I am {{ isAvailable() ? "available" : "not available" }}
+ `,
+})
+export class UserprofileComponent {
+ name = input("");
+ age = input(0);
+ favouriteColors = input([]);
+ isAvailable = input(false);
+}
diff --git a/content/4-component-composition/1-props/angular/app.component.ts b/content/4-component-composition/1-props/angular/app.component.ts
index f8a2cdf1..5c4d96a4 100644
--- a/content/4-component-composition/1-props/angular/app.component.ts
+++ b/content/4-component-composition/1-props/angular/app.component.ts
@@ -1,4 +1,5 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
+import { UserprofileModule } from "./userprofile.component";
@Component({
selector: "app-root",
@@ -13,3 +14,10 @@ import { Component } from "@angular/core";
`,
})
export class AppComponent {}
+
+@NgModule({
+ declarations: [AppComponent],
+ imports: [UserprofileModule],
+ bootstrap: [AppComponent],
+})
+export class AppModule {}
diff --git a/content/4-component-composition/1-props/angular/userprofile.component.ts b/content/4-component-composition/1-props/angular/userprofile.component.ts
index 6ad0bb65..05745b04 100644
--- a/content/4-component-composition/1-props/angular/userprofile.component.ts
+++ b/content/4-component-composition/1-props/angular/userprofile.component.ts
@@ -1,4 +1,4 @@
-import { Component, Input } from "@angular/core";
+import { Component, Input, NgModule } from "@angular/core";
@Component({
selector: "app-userprofile",
@@ -15,3 +15,9 @@ export class UserprofileComponent {
@Input() favouriteColors: string[] = [];
@Input() isAvailable: boolean = false;
}
+
+@NgModule({
+ declarations: [UserprofileComponent],
+ exports: [UserprofileComponent],
+})
+export class UserprofileModule {}
diff --git a/content/4-component-composition/2-emit-to-parent/angular-renaissance/answer-button.component.ts b/content/4-component-composition/2-emit-to-parent/angular-renaissance/answer-button.component.ts
new file mode 100644
index 00000000..d097f992
--- /dev/null
+++ b/content/4-component-composition/2-emit-to-parent/angular-renaissance/answer-button.component.ts
@@ -0,0 +1,14 @@
+import { Component, output } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-answer-button",
+ template: `
+
+
+ `,
+})
+export class AnswerButtonComponent {
+ yes = output();
+ no = output();
+}
diff --git a/content/4-component-composition/2-emit-to-parent/angular-renaissance/app.component.ts b/content/4-component-composition/2-emit-to-parent/angular-renaissance/app.component.ts
new file mode 100644
index 00000000..ff2679c5
--- /dev/null
+++ b/content/4-component-composition/2-emit-to-parent/angular-renaissance/app.component.ts
@@ -0,0 +1,27 @@
+import { Component, signal } from "@angular/core";
+import { AnswerButtonComponent } from "./answer-button.component";
+
+@Component({
+ standalone: true,
+ selector: "app-root",
+ imports: [AnswerButtonComponent],
+ template: `
+ Are you happy?
+
+
+
+
+ {{ isHappy() ? "😀" : "😥" }}
+ `,
+})
+export class AppComponent {
+ isHappy = signal(true);
+
+ onAnswerYes() {
+ this.isHappy.set(true);
+ }
+
+ onAnswerNo() {
+ this.isHappy.set(false);
+ }
+}
diff --git a/content/4-component-composition/2-emit-to-parent/angular/answer-button.component.ts b/content/4-component-composition/2-emit-to-parent/angular/answer-button.component.ts
index d7a6129a..51aaafa0 100644
--- a/content/4-component-composition/2-emit-to-parent/angular/answer-button.component.ts
+++ b/content/4-component-composition/2-emit-to-parent/angular/answer-button.component.ts
@@ -1,4 +1,4 @@
-import { Component, Output, EventEmitter } from "@angular/core";
+import { Component, Output, EventEmitter, NgModule } from "@angular/core";
@Component({
selector: "app-answer-button",
@@ -11,3 +11,9 @@ export class AnswerButtonComponent {
@Output() yes = new EventEmitter();
@Output() no = new EventEmitter();
}
+
+@NgModule({
+ declarations: [AnswerButtonComponent],
+ exports: [AnswerButtonComponent],
+})
+export class AnswerButtonModule {}
diff --git a/content/4-component-composition/2-emit-to-parent/angular/app.component.ts b/content/4-component-composition/2-emit-to-parent/angular/app.component.ts
index 17504d64..d15ecfa4 100644
--- a/content/4-component-composition/2-emit-to-parent/angular/app.component.ts
+++ b/content/4-component-composition/2-emit-to-parent/angular/app.component.ts
@@ -1,4 +1,5 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
+import { AnswerButtonModule } from "./answer-button.component";
@Component({
selector: "app-root",
@@ -22,3 +23,10 @@ export class AppComponent {
this.isHappy = false;
}
}
+
+@NgModule({
+ declarations: [AppComponent],
+ imports: [AnswerButtonModule],
+ bootstrap: [AppComponent],
+})
+export class AppModule {}
diff --git a/content/4-component-composition/3-slot/angular-renaissance/app.component.ts b/content/4-component-composition/3-slot/angular-renaissance/app.component.ts
new file mode 100644
index 00000000..a3c322e0
--- /dev/null
+++ b/content/4-component-composition/3-slot/angular-renaissance/app.component.ts
@@ -0,0 +1,10 @@
+import { Component } from "@angular/core";
+import { FunnyButtonComponent } from "./funny-button.component";
+
+@Component({
+ standalone: true,
+ selector: "app-root",
+ imports: [FunnyButtonComponent],
+ template: `Click me!`,
+})
+export class AppComponent {}
diff --git a/content/4-component-composition/3-slot/angular-renaissance/funny-button.component.ts b/content/4-component-composition/3-slot/angular-renaissance/funny-button.component.ts
new file mode 100644
index 00000000..4b6db278
--- /dev/null
+++ b/content/4-component-composition/3-slot/angular-renaissance/funny-button.component.ts
@@ -0,0 +1,26 @@
+import { Component } from "@angular/core";
+
+@Component({
+ standalone: true,
+ selector: "app-funny-button",
+ styles: `
+ button {
+ background: rgba(0, 0, 0, 0.4);
+ color: #fff;
+ padding: 10px 20px;
+ font-size: 30px;
+ border: 2px solid #fff;
+ margin: 8px;
+ transform: scale(0.9);
+ box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
+ transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
+ outline: 0;
+ }
+ `,
+ template: `
+
+ `,
+})
+export class FunnyButtonComponent {}
diff --git a/content/4-component-composition/3-slot/angular/app.component.ts b/content/4-component-composition/3-slot/angular/app.component.ts
index 8fb72406..2acf3424 100644
--- a/content/4-component-composition/3-slot/angular/app.component.ts
+++ b/content/4-component-composition/3-slot/angular/app.component.ts
@@ -1,7 +1,15 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
+import { FunnyButtonModule } from "./funny-button.component";
@Component({
selector: "app-root",
template: `Click me!`,
})
export class AppComponent {}
+
+@NgModule({
+ declarations: [AppComponent],
+ imports: [FunnyButtonModule],
+ bootstrap: [AppComponent],
+})
+export class AppModule {}
diff --git a/content/4-component-composition/3-slot/angular/funny-button.component.css b/content/4-component-composition/3-slot/angular/funny-button.component.css
deleted file mode 100644
index f138778a..00000000
--- a/content/4-component-composition/3-slot/angular/funny-button.component.css
+++ /dev/null
@@ -1,12 +0,0 @@
-button {
- background: rgba(0, 0, 0, 0.4);
- color: #fff;
- padding: 10px 20px;
- font-size: 30px;
- border: 2px solid #fff;
- margin: 8px;
- transform: scale(0.9);
- box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
- transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
- outline: 0;
-}
diff --git a/content/4-component-composition/3-slot/angular/funny-button.component.ts b/content/4-component-composition/3-slot/angular/funny-button.component.ts
index 5f32a1ef..bb515578 100644
--- a/content/4-component-composition/3-slot/angular/funny-button.component.ts
+++ b/content/4-component-composition/3-slot/angular/funny-button.component.ts
@@ -1,8 +1,23 @@
-import { Component } from "@angular/core";
+import { Component, NgModule } from "@angular/core";
@Component({
selector: "app-funny-button",
- styleUrls: ["./funny-button.component.css"],
+ styles: [
+ `
+ button {
+ background: rgba(0, 0, 0, 0.4);
+ color: #fff;
+ padding: 10px 20px;
+ font-size: 30px;
+ border: 2px solid #fff;
+ margin: 8px;
+ transform: scale(0.9);
+ box-shadow: 4px 4px rgba(0, 0, 0, 0.4);
+ transition: transform 0.2s cubic-bezier(0.34, 1.65, 0.88, 0.925) 0s;
+ outline: 0;
+ }
+ `,
+ ],
template: `