Codecademy Logo

Building Interactive Angular Components Using AI

Related learning

  • Learn how to build Angular applications using AI tools to generate code, evaluate patterns, and develop real-world web apps.
    • With Certificate
    • Intermediate.
      3 hours

Angular Signal Input

In Angular, the input() function creates signal-based component inputs that update automatically when their values change. These inputs are read-only signals that can be accessed in the component’s template or class using the signal getter syntax.

import { Component, input } from '@angular/core';
@Component({
selector: 'app-child',
template: `<p>Value: {{ value() }}</p>`
})
export class ChildComponent {
value = input<number>();
}
@Component({
selector: 'app-parent',
template: `<app-child [value]="10" />`
})
export class ParentComponent {}

Angular Signal model() Function

In Angular, the model() function creates a special signal that enables two-way data binding by combining input and output functionality. Changes can flow both from parent to child and from child back to parent.

import { Component, model } from '@angular/core';
// Child component
@Component({
selector: 'app-child',
template: '<button (click)="increment()">Increment</button>'
})
export class ChildComponent {
value = model<number>(0);
increment() {
this.value.update(val => val + 1);
}
}
// Parent Component
@Component({
selector: 'app-parent',
template: '<app-child [(value)]="parentValue"></app-child>'
})
export class ParentComponent {
parentValue = signal(10);
}

Angular Communication Patterns

When using Angular, choose between parent-child communication for related components and service-based communication for broader data sharing. The decision depends on the component relationship and how widely the data needs to be accessed or modified. Parent-child communication is often simpler but is limited to direct interactions, while service-based methods allow for more complex, global data sharing across different components.

Angular Signals Communication

Angular components can communicate through direct parent-child relationships using Signal inputs and model signals. Signals provide a modern, reactive way to pass data from parent to child (inputs) and enable two-way binding through model signals.

// Child Component
import { Component, input, model } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="incrementCount()">Increment</button>
<p>Count: {{ count() }}</p>
<p>Label: {{ label() }}</p>
`
})
export class ChildComponent {
// Signal input - receives data from parent (read-only)
label = input<string>('default label');
// Model signal - two-way binding with parent
count = model<number>(0);
incrementCount() {
this.count.set(this.count() + 1);
}
}
// Parent Component
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child
[label]="'Counter'"
[(count)]="parentCount()">
</app-child>
<p>Parent sees count: {{ parentCount() }}</p>
`
})
export class ParentComponent {
parentCount = signal(0);
}

Angular Services

Services enable communication between unrelated components by providing a shared reactive state across the application. This decouples components and allows them to exchange data and events without direct parent-child relationships.

// Shared Service
import { Injectable, Component, inject, signal } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class DataService {
message = signal<string>('');
updateMessage(msg: string) {
this.message.set(msg);
}
}
// Component A - Updates shared state
@Component({
selector: 'app-component-a',
template: `<button (click)="dataService.updateMessage('Hello')">Send</button>`
})
export class ComponentA {
dataService = inject(DataService);
}
// Component B - Reads shared state
@Component({
selector: 'app-component-b',
template: `<p>{{ dataService.message() }}</p>`
})
export class ComponentB {
dataService = inject(DataService);
}

Services in Angular

In Angular, services encapsulate reusable functionality, allowing for centralized logic that can be shared across multiple components. This promotes better code organization and maintainability and reduces redundancy within the application.

@Injectable Decorator in Angular

The @Injectable decorator designates a class as a service in Angular, allowing Angular to manage its creation and distribution.

import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MyService {
// Service logic
}

Angular root Provider

In Angular, setting providedIn: 'root' in the @Injectable decorator registers the service with the root injector, making it available throughout the entire application as a single shared instance.

@Injectable({
providedIn: 'root'
})
export class MyService { }

Angular Service Injection

Angular allows the injection of services into components to enable functionality. The inject() method enables service injection directly within the component’s class body, making services immediately available for use. Once injected, components gain access to the service’s shared state and methods, allowing multiple components to work with the same data.

import { Component, inject } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-profile',
template: `<p>Welcome, {{ userService.currentUser().name }}</p>`
})
export class ProfileComponent {
userService = inject(UserService);
}
@Component({
selector: 'app-dashboard',
template: `<p>User ID: {{ userService.currentUser().id }}</p>`
})
export class DashboardComponent {
userService = inject(UserService);
}

Angular Signals

In Angular, signals are used to manage reactive state by storing a value and automatically updating any dependent components or views when the value changes.

import { WritableSignal, signal } from '@angular/core';
export class ExampleComponent {
count: WritableSignal<number> = signal(0);
increment() {
this.count.update(value => value + 1);
}
}

Angular signal() Function

In Angular, the signal() function is used to create a signal with an initial value that can be updated and observed reactively.

import { signal, WritableSignal } from '@angular/core';
export class ExampleComponent {
count: WritableSignal<number> = signal(0);
increment() {
this.count.update(n => n + 1);
}
}

Learn more on Codecademy

  • Learn how to build Angular applications using AI tools to generate code, evaluate patterns, and develop real-world web apps.
    • With Certificate
    • Intermediate.
      3 hours