diff --git a/adev/src/content/tutorials/signals/steps/1-creating-your-first-signal/README.md b/adev/src/content/tutorials/signals/steps/1-creating-your-first-signal/README.md
index 1d626525703..cd2cf9372d8 100644
--- a/adev/src/content/tutorials/signals/steps/1-creating-your-first-signal/README.md
+++ b/adev/src/content/tutorials/signals/steps/1-creating-your-first-signal/README.md
@@ -8,9 +8,9 @@ In this activity, you'll learn how to:
- Display its value in a template
- Update the signal value using `set()` and `update()` methods
-
+Let's build an interactive user status system with signals!
-Let's build an interactive user status system with signals.
+
@@ -38,18 +38,25 @@ export class App {
-Update the template to display the current user status by calling the signal `userStatus()` with parentheses.
+Update the status indicator to display the current user status by:
+1. Binding the signal to the class attribute with `[class]="userStatus()"`
+2. Displaying the status text by replacing `???` with `{{ userStatus() }}`
```html
-
-
User Dashboard
-
-
- Status: {{ userStatus() }}
-
+
+
+
+ Status: ???
+
+
+
+
+
+ Status: {{ userStatus() }}
```
+Notice how we call the signal `userStatus()` with parentheses to read its value.
@@ -69,25 +76,19 @@ The `set()` method replaces the signal's value entirely with a new value.
-
-Add control buttons to the template for changing the user's status.
+
+The buttons are already in the template. Now connect them to your methods by adding:
+1. Click handlers with `(click)`
+2. Disabled states with `[disabled]` when already in that status
```html
-
-
User Dashboard
-
-
-
-
-
-
-
-
-
+
+
+
```
@@ -105,17 +106,13 @@ The `update()` method takes a function that receives the current value and retur
-
-Add the toggle button to your status controls.
+
+The toggle button is already in the template. Connect it to your `toggleStatus()` method:
```html
-
`,
styleUrl: './app.css',
@@ -19,4 +31,7 @@ import {Component, ChangeDetectionStrategy} from '@angular/core';
})
export class App {
// TODO: Create a userStatus signal with type 'online' | 'offline' and the initial value of 'offline'
+ // TODO: Add goOnline() method using set()
+ // TODO: Add goOffline() method using set()
+ // TODO: Add toggleStatus() method using update()
}
diff --git a/adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/README.md b/adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/README.md
similarity index 86%
rename from adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/README.md
rename to adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/README.md
index 71fb6c42a76..780cdbdecff 100644
--- a/adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/README.md
+++ b/adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/README.md
@@ -1,8 +1,8 @@
# Reacting to signal changes with effect
-Now that you've learned [querying child elements with signal queries](/tutorials/signals/8-query-child-elements-with-signal-queries), let's explore how to react to signal changes with effects. Effects are functions that run automatically when their dependencies change, making them perfect for side effects like logging, DOM manipulation, or API calls.
+Now that you've learned [querying child elements with signal queries](/tutorials/signals/9-query-child-elements-with-signal-queries), let's explore how to react to signal changes with effects. Effects are functions that run automatically when their dependencies change, making them perfect for side effects like logging, DOM manipulation, or API calls.
-**Important: Effects should be your last resort.** Always prefer `computed()` for derived values and `linkedSignal()` for values that can be both derived and manually set. If you find yourself copying data from one signal to another with an effect, it's a sign you should move your source-of-truth higher up and use `computed()` or `linkedSignal()` instead. Effects are best for syncing signal state to imperative, non-signal APIs.
+**Important: Effects should be the last API you reach for.** Always prefer `computed()` for derived values and `linkedSignal()` for values that can be both derived and manually set. If you find yourself copying data from one signal to another with an effect, it's a sign you should move your source-of-truth higher up and use `computed()` or `linkedSignal()` instead. Effects are best for syncing signal state to imperative, non-signal APIs.
In this activity, you'll learn how to use the `effect()` function appropriately for legitimate side effects that respond to signal changes.
@@ -17,7 +17,7 @@ Add `effect` to your existing imports.
```ts
// Add effect to existing imports
-import {Component, signal, computed, effect} from '@angular/core';
+import {Component, signal, computed, effect, ChangeDetectionStrategy} from '@angular/core';
```
The `effect` function creates a reactive side effect that runs automatically when any signals it reads change.
diff --git a/adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/answer/src/app/app.css b/adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/answer/src/app/app.css
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/answer/src/app/app.css
rename to adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/answer/src/app/app.css
diff --git a/adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/answer/src/app/app.ts b/adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/answer/src/app/app.ts
similarity index 89%
rename from adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/answer/src/app/app.ts
rename to adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/answer/src/app/app.ts
index 3db42a61e50..87580f36f65 100644
--- a/adev/src/content/tutorials/signals/steps/9-reacting-to-signal-changes-with-effect/answer/src/app/app.ts
+++ b/adev/src/content/tutorials/signals/steps/10-reacting-to-signal-changes-with-effect/answer/src/app/app.ts
@@ -8,7 +8,12 @@ import {Component, signal, computed, effect, ChangeDetectionStrategy} from '@ang
Status:
+ @if (isLoggedIn()) {
+ Logged in
+ } @else {
+ Logged out
+ }
+
diff --git a/adev/src/content/tutorials/signals/steps/10-next-steps/README.md b/adev/src/content/tutorials/signals/steps/11-next-steps/README.md
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/10-next-steps/README.md
rename to adev/src/content/tutorials/signals/steps/11-next-steps/README.md
diff --git a/adev/src/content/tutorials/signals/steps/10-next-steps/config.json b/adev/src/content/tutorials/signals/steps/11-next-steps/config.json
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/10-next-steps/config.json
rename to adev/src/content/tutorials/signals/steps/11-next-steps/config.json
diff --git a/adev/src/content/tutorials/signals/steps/2-deriving-state-with-computed-signals/README.md b/adev/src/content/tutorials/signals/steps/2-deriving-state-with-computed-signals/README.md
index 99636e7e3c0..e0a5bc5cf07 100644
--- a/adev/src/content/tutorials/signals/steps/2-deriving-state-with-computed-signals/README.md
+++ b/adev/src/content/tutorials/signals/steps/2-deriving-state-with-computed-signals/README.md
@@ -4,9 +4,9 @@ Now that you've learned [how to create and update signals](/tutorials/signals/1-
In this activity, you'll learn how to use the `computed()` function to create derived state that updates automatically when the underlying signals change.
-
+Let's enhance our user status system by adding computed values that derive information from our user status signal. The starter code now includes three status options: `'online'`, `'away'`, and `'offline'`.
-Let's enhance our user status system by adding computed values that derive information from our user status signal.
+
@@ -15,7 +15,7 @@ Add `computed` to your existing imports.
```ts
// Add computed to existing imports
-import {Component, signal, computed} from '@angular/core';
+import {Component, signal, computed, ChangeDetectionStrategy} from '@angular/core';
```
@@ -64,41 +64,35 @@ This demonstrates how computed signals can perform calculations and combine mult
-Update your template to use the computed signals.
+The template already has placeholders showing "Loading...". Replace them with your computed signals:
+
+1. For notifications, replace `Loading...` with an @if block:
```html
-
-
- Within Working Hours: Loading...
+ Within Working Hours:
+
+ Loading...
diff --git a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/README.md b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/README.md
index a0922d2b1c1..5623d00ed35 100644
--- a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/README.md
+++ b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/README.md
@@ -1,23 +1,21 @@
# Deriving state with linked signals
-In the [previous lesson](/tutorials/signals/2-deriving-state-with-computed-signals), you created a computed signal for `notificationsEnabled` that automatically followed your user status. But what if users want to manually disable notifications even when they're online? That's where linked signals come in.
+Now that you've learned [how to derive state with computed signals](/tutorials/signals/2-deriving-state-with-computed-signals), you created a computed signal for `notificationsEnabled` that automatically followed your user status. But what if users want to manually disable notifications even when they're online? That's where linked signals come in.
Linked signals are writable signals that maintain a reactive connection to their source signals. They're perfect for creating state that normally follows a computation but can be overridden when needed.
-In this activity, you'll learn how `linkedSignal()` differs from `computed()` by converting your notifications example.
+In this activity, you'll learn how `linkedSignal()` differs from `computed()` by enhancing the previous user status system's computed `notificationsEnabled` to a writable linked signal.
-Let's enhance our user status system by converting the read-only computed `notificationsEnabled` to a writable linked signal.
-
Add `linkedSignal` to your existing imports.
```ts
-// Add linkedSignal to existing imports
-import {Component, signal, computed, linkedSignal} from '@angular/core';
+// Add linkedSignal to existing imports
+import {Component, signal, computed, linkedSignal, ChangeDetectionStrategy} from '@angular/core';
```
@@ -49,13 +47,13 @@ toggleNotifications() {
This is the key difference: computed signals are read-only, but linked signals can be updated manually while still maintaining their reactive connection.
-
+
Update your template to add a toggle button for notifications:
```html
- Notifications:
+ Notifications:
@if (notificationsEnabled()) {
Enabled
} @else {
@@ -94,4 +92,4 @@ Excellent! You've learned the key differences between computed and linked signal
- **Use computed when**: The value should always be calculated
- **Use linkedSignal when**: You need a default computation that can be overridden
-In the next lesson, you'll learn [how to manage async data with signals](/tutorials/signals/4-managing-async-data-with-signals)!
\ No newline at end of file
+In the next lesson, you'll learn [how to manage async data with signals](/tutorials/signals/4-managing-async-data-with-signals)!
diff --git a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.css b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.css
index af614fae588..073853b68e4 100644
--- a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.css
+++ b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.css
@@ -23,6 +23,18 @@
display: inline-block;
}
+.status-indicator.online .status-dot {
+ background: #4caf50;
+}
+
+.status-indicator.away .status-dot {
+ background: #ff9800;
+}
+
+.status-indicator.offline .status-dot {
+ background: #f44336;
+}
+
.status-info {
margin: 20px 0;
padding: 16px;
@@ -32,7 +44,7 @@
border-left-color: var(--status-color);
}
-.availability, .message {
+.notifications, .message, .working-hours {
margin: 8px 0;
}
@@ -95,4 +107,12 @@ button:disabled {
.status-controls .toggle-btn {
background-color: #28a745;
+}
+
+.notifications .override-btn {
+ background-color: #ffc107;
+ color: #212529;
+ margin-left: 8px;
+ font-size: 0.8em;
+ padding: 4px 8px;
}
\ No newline at end of file
diff --git a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.ts b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.ts
index b5b33802faf..979f9948829 100644
--- a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.ts
+++ b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/answer/src/app/app.ts
@@ -103,17 +103,17 @@ export class App {
}
toggleStatus() {
- this.userStatus.update((current: 'online' | 'offline' | 'away') => {
- switch (current) {
- case 'offline':
- return 'online';
- case 'online':
- return 'away';
- case 'away':
- return 'offline';
- default:
- return 'offline';
- }
- });
+ const current = this.userStatus();
+ switch (current) {
+ case 'offline':
+ this.userStatus.set('online');
+ break;
+ case 'online':
+ this.userStatus.set('away');
+ break;
+ case 'away':
+ this.userStatus.set('offline');
+ break;
+ }
}
}
diff --git a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.css b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.css
index af614fae588..073853b68e4 100644
--- a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.css
+++ b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.css
@@ -23,6 +23,18 @@
display: inline-block;
}
+.status-indicator.online .status-dot {
+ background: #4caf50;
+}
+
+.status-indicator.away .status-dot {
+ background: #ff9800;
+}
+
+.status-indicator.offline .status-dot {
+ background: #f44336;
+}
+
.status-info {
margin: 20px 0;
padding: 16px;
@@ -32,7 +44,7 @@
border-left-color: var(--status-color);
}
-.availability, .message {
+.notifications, .message, .working-hours {
margin: 8px 0;
}
@@ -95,4 +107,12 @@ button:disabled {
.status-controls .toggle-btn {
background-color: #28a745;
+}
+
+.notifications .override-btn {
+ background-color: #ffc107;
+ color: #212529;
+ margin-left: 8px;
+ font-size: 0.8em;
+ padding: 4px 8px;
}
\ No newline at end of file
diff --git a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.ts b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.ts
index 0875bd6b68c..a86301c86df 100644
--- a/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.ts
+++ b/adev/src/content/tutorials/signals/steps/3-deriving-state-with-linked-signals/src/app/app.ts
@@ -11,10 +11,15 @@ import {Component, signal, computed, ChangeDetectionStrategy} from '@angular/cor
Status: {{ userStatus() }}
- @for (item of []; track item.id) {
+ @for (item of cartStore.cartItems(); track item.id) {
{{ item.name }}
@@ -39,8 +38,8 @@ import {CartStore} from './cart-store';
-
-
Total: $0
+
Total Items: {{ cartStore.totalQuantity() }}
+
Total: \${{ cartStore.totalPrice() }}
Clear Cart
}
@@ -64,11 +63,13 @@ export class CartDisplay {
}
increaseQuantity(id: string) {
- // TODO: Get current item and update quantity
+ // TODO: Get current item from cartStore.cartItems()
+ // and call cartStore.updateQuantity() with quantity + 1
}
decreaseQuantity(id: string) {
- // TODO: Get current item and update quantity
+ // TODO: Get current item from cartStore.cartItems()
+ // and call cartStore.updateQuantity() with quantity - 1 (if > 1)
}
removeItem(id: string) {
diff --git a/adev/src/content/tutorials/signals/steps/6-using-signals-with-services/src/app/cart-store.ts b/adev/src/content/tutorials/signals/steps/7-using-signals-with-services/src/app/cart-store.ts
similarity index 77%
rename from adev/src/content/tutorials/signals/steps/6-using-signals-with-services/src/app/cart-store.ts
rename to adev/src/content/tutorials/signals/steps/7-using-signals-with-services/src/app/cart-store.ts
index 92467f3c280..d80d9048bf3 100644
--- a/adev/src/content/tutorials/signals/steps/6-using-signals-with-services/src/app/cart-store.ts
+++ b/adev/src/content/tutorials/signals/steps/7-using-signals-with-services/src/app/cart-store.ts
@@ -7,11 +7,14 @@ import {CartItem} from './cart-types';
export class CartStore {
private items = signal([]);
- // TODO: Create readonly signal for items using asReadonly()
+ // TODO: Create readonly signal for cartItems using this.items.asReadonly()
+ // readonly cartItems = ???
- // TODO: Create computed signal for total quantity
+ // TODO: Create computed signal for totalQuantity
+ // readonly totalQuantity = computed(() => ???)
- // TODO: Create computed signal for total price
+ // TODO: Create computed signal for totalPrice
+ // readonly totalPrice = computed(() => ???)
addItem(id: string, name: string, price: number) {
this.items.update((currentItems) => {
diff --git a/adev/src/content/tutorials/signals/steps/6-using-signals-with-services/src/app/cart-types.ts b/adev/src/content/tutorials/signals/steps/7-using-signals-with-services/src/app/cart-types.ts
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/6-using-signals-with-services/src/app/cart-types.ts
rename to adev/src/content/tutorials/signals/steps/7-using-signals-with-services/src/app/cart-types.ts
diff --git a/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/README.md b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/README.md
new file mode 100644
index 00000000000..aae2a5d690f
--- /dev/null
+++ b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/README.md
@@ -0,0 +1,110 @@
+# Using signals with directives
+
+Now that you've learned [using signals with services](/tutorials/signals/7-using-signals-with-services), let's explore how directives use signals. **The great news: signals work exactly the same in directives as they do in components!** The main difference is that since directives don't have templates, you'll primarily use signals in host bindings to reactively update the host element.
+
+In this activity, you'll build a highlight directive that demonstrates how signals create reactive behavior in directives.
+
+
+
+
+
+
+Import the signal functions and create your reactive state. This works exactly the same as in components:
+
+```ts
+import {Directive, input, signal, computed} from '@angular/core';
+
+@Directive({
+ selector: '[highlight]',
+})
+export class HighlightDirective {
+ // Signal inputs - same as components!
+ color = input('yellow');
+ intensity = input(0.3);
+
+ // Internal state - same as components!
+ private isHovered = signal(false);
+
+ // Computed signals - same as components!
+ backgroundStyle = computed(() => {
+ const baseColor = this.color();
+ const alpha = this.isHovered() ? this.intensity() : this.intensity() * 0.5;
+
+ const colorMap: Record = {
+ 'yellow': `rgba(255, 255, 0, ${alpha})`,
+ 'blue': `rgba(0, 100, 255, ${alpha})`,
+ 'green': `rgba(0, 200, 0, ${alpha})`,
+ 'red': `rgba(255, 0, 0, ${alpha})`,
+ };
+
+ return colorMap[baseColor] || colorMap['yellow'];
+ });
+}
+```
+
+Notice how this is identical to component patterns - the only difference is we're in a `@Directive` instead of `@Component`.
+
+
+
+Since directives don't have templates, you'll use signals in **host bindings** to reactively update the host element. Add the `host` configuration and event handlers:
+
+```ts
+@Directive({
+ selector: '[highlight]',
+ host: {
+ '[style.backgroundColor]': 'backgroundStyle()',
+ '(mouseenter)': 'onMouseEnter()',
+ '(mouseleave)': 'onMouseLeave()',
+ },
+})
+export class HighlightDirective {
+ // ... signals from previous step ...
+
+ onMouseEnter() {
+ this.isHovered.set(true);
+ }
+
+ onMouseLeave() {
+ this.isHovered.set(false);
+ }
+}
+```
+
+The host bindings automatically re-evaluate when the signals change - just like template bindings in components! When `isHovered` changes, the `backgroundStyle` computed signal recalculates, and the host binding updates the element's style.
+
+
+
+Update the app template to demonstrate the reactive directive:
+
+```ts
+template: `
+
+
Directive with Signals
+
+
+ Hover me - Yellow highlight
+
+
+
+ Hover me - Blue highlight
+
+
+
+ Hover me - Green highlight
+
+
+`,
+```
+
+The directive automatically applies reactive highlighting based on the signal inputs!
+
+
+
+
+Perfect! You've now seen how signals work with directives. Some key takeaways from this lesson are:
+
+- **Signals are universal** - All signal APIs (`input()`, `signal()`, `computed()`, `effect()`) work the same in both directives and components
+- **Host bindings are the primary use case** - Since directives don't have templates, you use signals in host bindings to reactively modify the host element
+- **Same reactive patterns** - Signal updates trigger automatic re-evaluation of computed signals and host bindings, just like in component templates
+
+In the next lesson, you'll [learn how to query child elements with signal queries](/tutorials/signals/9-query-child-elements-with-signal-queries)!
diff --git a/adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/answer/src/app/app.css b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/answer/src/app/app.css
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/answer/src/app/app.css
rename to adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/answer/src/app/app.css
diff --git a/adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/answer/src/app/app.ts b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/answer/src/app/app.ts
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/answer/src/app/app.ts
rename to adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/answer/src/app/app.ts
diff --git a/adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/answer/src/app/highlight-directive.ts b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/answer/src/app/highlight-directive.ts
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/answer/src/app/highlight-directive.ts
rename to adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/answer/src/app/highlight-directive.ts
diff --git a/adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/config.json b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/config.json
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/config.json
rename to adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/config.json
diff --git a/adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/src/app/app.css b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/src/app/app.css
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/src/app/app.css
rename to adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/src/app/app.css
diff --git a/adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/src/app/app.ts b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/src/app/app.ts
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/src/app/app.ts
rename to adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/src/app/app.ts
diff --git a/adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/src/app/highlight-directive.ts b/adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/src/app/highlight-directive.ts
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/7-using-signals-with-directives/src/app/highlight-directive.ts
rename to adev/src/content/tutorials/signals/steps/8-using-signals-with-directives/src/app/highlight-directive.ts
diff --git a/adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/README.md b/adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/README.md
similarity index 76%
rename from adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/README.md
rename to adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/README.md
index 3b544eab652..8354746f5de 100644
--- a/adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/README.md
+++ b/adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/README.md
@@ -1,6 +1,6 @@
# Query child elements with signal queries
-Now that you've learned [how to use signals with directives](/tutorials/signals/7-using-signals-with-directives), let's explore signal-based query APIs. These provide a reactive way to access and interact with child components. Unlike traditional ViewChild, signal queries automatically update and provide type-safe access to child components.
+Now that you've learned [how to use signals with directives](/tutorials/signals/8-using-signals-with-directives), let's explore signal-based query APIs. These provide a reactive way to access and interact with child components and directives. Both components and directives can perform queries while also being queried themselves. Unlike the traditional ViewChild, signal queries automatically update and provide type-safe access to child components and directives.
In this activity, you'll add viewChild queries to interact with child components programmatically.
@@ -12,7 +12,7 @@ In this activity, you'll add viewChild queries to interact with child components
First, add the `viewChild` import to access child components in `app.ts`.
```ts
-import {Component, signal, computed, viewChild} from '@angular/core';
+import {Component, signal, computed, viewChild, ChangeDetectionStrategy} from '@angular/core';
```
@@ -63,4 +63,4 @@ Click the buttons to see how viewChild queries enable parent components to contr
Perfect! You've learned how to use signal-based query APIs for child component interaction:
-In the next lesson, you'll learn about [how to react to signal changes with effect](/tutorials/signals/9-reacting-to-signal-changes-with-effect)!
+In the next lesson, you'll learn about [how to react to signal changes with effect](/tutorials/signals/10-reacting-to-signal-changes-with-effect)!
diff --git a/adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/answer/src/app/app.css b/adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/app.css
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/answer/src/app/app.css
rename to adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/app.css
diff --git a/adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/answer/src/app/app.ts b/adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/app.ts
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/answer/src/app/app.ts
rename to adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/app.ts
diff --git a/adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/answer/src/app/cart-summary.ts b/adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/cart-summary.ts
similarity index 100%
rename from adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/answer/src/app/cart-summary.ts
rename to adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/cart-summary.ts
diff --git a/adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/src/app/product-card.ts b/adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/product-card.ts
similarity index 80%
rename from adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/src/app/product-card.ts
rename to adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/product-card.ts
index f46acef3ac3..63994e205c9 100644
--- a/adev/src/content/tutorials/signals/steps/8-query-child-elements-with-signal-queries/src/app/product-card.ts
+++ b/adev/src/content/tutorials/signals/steps/9-query-child-elements-with-signal-queries/answer/src/app/product-card.ts
@@ -9,7 +9,11 @@ import {Component, input, signal, ChangeDetectionStrategy} from '@angular/core';