Inputs: input()
An input is a component field whose value is set by the parent. This way one component can be used many times with different data: for example, a single-task component is rendered for every task in the list.
Creating the task component
ng generate component todo-itemThe folder src/app/todo-item appears with todo-item.ts, todo-item.html, todo-item.css and a test.
Declaring an input
The input() function creates an input. It works like a read-only signal: you read the value by calling it with parentheses.
// src/app/todo-item/todo-item.ts
import { Component, input } from '@angular/core';
@Component({
selector: 'app-todo-item',
templateUrl: './todo-item.html',
styleUrl: './todo-item.css',
})
export class TodoItem {
title = input('');
}<!-- src/app/todo-item/todo-item.html -->
<span>{{ title() }}</span>The argument of input('') is the default value: until the parent passes anything, an empty string is shown.
Passing a value from the parent
The parent adds the component to imports and passes the value with property binding:
// src/app/todo-list/todo-list.ts
import { Component, signal } from '@angular/core';
import { TodoItem } from '../todo-item/todo-item';
import { Todo } from '../todo';
@Component({
selector: 'app-todo-list',
imports: [TodoItem],
templateUrl: './todo-list.html',
})
export class TodoList {
todos = signal<Todo[]>([
{ id: 1, title: 'Buy bread', done: true },
{ id: 2, title: 'Call Oleg', done: false },
]);
}<!-- src/app/todo-list/todo-list.html -->
<ul>
@for (todo of todos(); track todo.id) {
<li><app-todo-item [title]="todo.title" /></li>
}
</ul>The page shows two items: "Buy bread" and "Call Oleg". A constant string can be passed without brackets: <app-todo-item title="Buy bread" />.
A required input
The task component needs the whole object, not just the title. Without a task the component makes no sense, so we make the input required:
// src/app/todo-item/todo-item.ts
import { Component, input } from '@angular/core';
import { Todo } from '../todo';
@Component({
selector: 'app-todo-item',
templateUrl: './todo-item.html',
styleUrl: './todo-item.css',
})
export class TodoItem {
todo = input.required<Todo>();
}<!-- src/app/todo-item/todo-item.html -->
<span [class.done]="todo().done">{{ todo().title }}</span>The parent's template now says <app-todo-item [todo]="todo" />. If you forget to pass todo, the build reports an error before the app even runs.
Deriving values from an input
An input is a signal, so you can build a computed from it:
// src/app/todo-item/todo-item.ts
label = computed(() => (this.todo().done ? 'done' : 'in progress'));label() recalculates by itself when the parent passes another task. Remember to import computed from @angular/core.
Common mistake
Trying to change an input from inside: this.todo.set(...). An input has no set method — the parent owns the data. If the child wants to change something, it tells the parent through an output, which is the topic of the next lesson.