> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angular/angular/llms.txt
> Use this file to discover all available pages before exploring further.

# Input & Output

> Decorators and functions for component communication

## Overview

Angular provides two primary mechanisms for component communication: inputs for passing data from parent to child, and outputs for emitting events from child to parent.

## @Input Decorator

### Signature

```typescript theme={null}
@Input(options?: string | Input): PropertyDecorator
```

### Parameters

<ParamField path="options" type="string | Input">
  Either an alias string or a configuration object.
</ParamField>

### Input Options

<ParamField path="alias" type="string">
  Alternative name for the input in templates.

  ```typescript theme={null}
  @Input({ alias: 'userName' }) name!: string;
  ```
</ParamField>

<ParamField path="required" type="boolean">
  Whether the input must be provided. Causes compile error if missing.

  ```typescript theme={null}
  @Input({ required: true }) userId!: number;
  ```
</ParamField>

<ParamField path="transform" type="(value: any) => any">
  Function to transform the input value before assignment.

  ```typescript theme={null}
  @Input({ transform: booleanAttribute }) disabled: boolean = false;
  ```
</ParamField>

### Basic Input Example

```typescript user-card.component.ts theme={null}
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-user-card',
  standalone: true,
  template: `
    <div class="card">
      <h3>{{name}}</h3>
      <p>{{email}}</p>
      <span class="badge">{{role}}</span>
    </div>
  `
})
export class UserCardComponent {
  @Input() name: string = '';
  @Input() email: string = '';
  @Input() role: string = 'user';
}
```

Usage:

```html theme={null}
<app-user-card 
  name="John Doe" 
  email="john@example.com" 
  role="admin">
</app-user-card>
```

### Input with Alias

```typescript product.component.ts theme={null}
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-product',
  standalone: true,
  template: `
    <div>
      <h4>{{productName}}</h4>
      <p>Price: ${{productPrice}}</p>
    </div>
  `
})
export class ProductComponent {
  @Input({ alias: 'name' }) productName!: string;
  @Input({ alias: 'price' }) productPrice!: number;
}
```

Usage:

```html theme={null}
<app-product name="Laptop" [price]="999"></app-product>
```

### Required Inputs

```typescript profile.component.ts theme={null}
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-profile',
  standalone: true,
  template: `
    <div>
      <h2>{{userId}}</h2>
      <p>{{bio || 'No bio available'}}</p>
    </div>
  `
})
export class ProfileComponent {
  // Compile error if not provided
  @Input({ required: true }) userId!: string;
  
  // Optional input
  @Input() bio?: string;
}
```

### Input Transforms

```typescript toggle.component.ts theme={null}
import { Component, Input, booleanAttribute, numberAttribute } from '@angular/core';

@Component({
  selector: 'app-toggle',
  standalone: true,
  template: `
    <button 
      [disabled]="disabled" 
      [style.width.px]="width">
      {{label}}
    </button>
  `
})
export class ToggleComponent {
  @Input({ transform: booleanAttribute }) disabled = false;
  @Input({ transform: numberAttribute }) width = 100;
  @Input() label = 'Toggle';
}
```

Usage:

```html theme={null}
<!-- String "true" converted to boolean true -->
<app-toggle disabled="true" width="200"></app-toggle>

<!-- Boolean attribute converted to true -->
<app-toggle disabled></app-toggle>
```

## input() Function (Signal-Based)

### Signature

```typescript theme={null}
input<T>(initialValue?: T, options?: InputOptions<T>): InputSignal<T>
input.required<T>(options?: InputOptions<T>): InputSignal<T>
```

### Signal Input Example

```typescript counter.component.ts theme={null}
import { Component, input, computed } from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `
    <div>
      <p>Count: {{count()}}</p>
      <p>Double: {{doubled()}}</p>
      <p>Label: {{label()}}</p>
    </div>
  `
})
export class CounterComponent {
  // Optional with default
  count = input(0);
  
  // Optional without default
  label = input<string>();
  
  // Derived value
  doubled = computed(() => this.count() * 2);
}
```

Usage:

```html theme={null}
<app-counter [count]="5" label="Items"></app-counter>
```

### Required Signal Input

```typescript item-detail.component.ts theme={null}
import { Component, input } from '@angular/core';

interface Item {
  id: number;
  name: string;
  description: string;
}

@Component({
  selector: 'app-item-detail',
  standalone: true,
  template: `
    <div>
      <h3>{{item().name}}</h3>
      <p>{{item().description}}</p>
    </div>
  `
})
export class ItemDetailComponent {
  // Required signal input
  item = input.required<Item>();
}
```

### Signal Input with Transform

```typescript date-display.component.ts theme={null}
import { Component, input } from '@angular/core';

@Component({
  selector: 'app-date-display',
  standalone: true,
  template: `
    <div>Date: {{formattedDate()}}</div>
  `
})
export class DateDisplayComponent {
  date = input('', {
    transform: (value: string | Date) => {
      if (typeof value === 'string') {
        return new Date(value);
      }
      return value;
    }
  });
  
  formattedDate = computed(() => {
    const d = this.date();
    return d ? d.toLocaleDateString() : '';
  });
}
```

## @Output Decorator

### Signature

```typescript theme={null}
@Output(alias?: string): PropertyDecorator
```

### Parameters

<ParamField path="alias" type="string">
  Alternative name for the output in templates.
</ParamField>

### Basic Output Example

```typescript button.component.ts theme={null}
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-button',
  standalone: true,
  template: `
    <button (click)="handleClick()">
      {{label}}
    </button>
  `
})
export class ButtonComponent {
  @Output() clicked = new EventEmitter<void>();
  label = 'Click Me';

  handleClick() {
    this.clicked.emit();
  }
}
```

Usage:

```html theme={null}
<app-button (clicked)="onButtonClick()"></app-button>
```

### Output with Data

```typescript search.component.ts theme={null}
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-search',
  standalone: true,
  template: `
    <input 
      #input
      type="text" 
      (input)="onSearch(input.value)">
  `
})
export class SearchComponent {
  @Output() search = new EventEmitter<string>();

  onSearch(query: string) {
    this.search.emit(query);
  }
}
```

Usage:

```html theme={null}
<app-search (search)="handleSearch($event)"></app-search>
```

```typescript theme={null}
handleSearch(query: string) {
  console.log('Search query:', query);
}
```

### Output with Alias

```typescript dropdown.component.ts theme={null}
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-dropdown',
  standalone: true,
  template: `
    <select (change)="onValueChange($event)">
      <option value="1">Option 1</option>
      <option value="2">Option 2</option>
    </select>
  `
})
export class DropdownComponent {
  @Output('valueChange') valueChanged = new EventEmitter<string>();

  onValueChange(event: Event) {
    const value = (event.target as HTMLSelectElement).value;
    this.valueChanged.emit(value);
  }
}
```

Usage:

```html theme={null}
<app-dropdown (valueChange)="onDropdownChange($event)"></app-dropdown>
```

## output() Function (Signal-Based)

### Signature

```typescript theme={null}
output<T = void>(options?: OutputOptions): OutputEmitterRef<T>
```

### Signal Output Example

```typescript modern-button.component.ts theme={null}
import { Component, input, output } from '@angular/core';

@Component({
  selector: 'app-modern-button',
  standalone: true,
  template: `
    <button (click)="handleClick()">
      {{label()}}
    </button>
  `
})
export class ModernButtonComponent {
  label = input('Click');
  clicked = output<void>();

  handleClick() {
    this.clicked.emit();
  }
}
```

### Output with Custom Event Type

```typescript item-list.component.ts theme={null}
import { Component, output } from '@angular/core';

interface ItemSelectedEvent {
  id: number;
  name: string;
  timestamp: Date;
}

@Component({
  selector: 'app-item-list',
  standalone: true,
  template: `
    <div *ngFor="let item of items" (click)="selectItem(item)">
      {{item.name}}
    </div>
  `
})
export class ItemListComponent {
  itemSelected = output<ItemSelectedEvent>();
  
  items = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' }
  ];

  selectItem(item: {id: number, name: string}) {
    this.itemSelected.emit({
      ...item,
      timestamp: new Date()
    });
  }
}
```

## Two-Way Binding

### NgModel Pattern

```typescript custom-input.component.ts theme={null}
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-custom-input',
  standalone: true,
  template: `
    <input 
      [value]="value" 
      (input)="onValueChange($event)">
  `
})
export class CustomInputComponent {
  @Input() value: string = '';
  @Output() valueChange = new EventEmitter<string>();

  onValueChange(event: Event) {
    const newValue = (event.target as HTMLInputElement).value;
    this.valueChange.emit(newValue);
  }
}
```

Usage:

```html theme={null}
<app-custom-input [(value)]="username"></app-custom-input>
```

### Signal-Based Two-Way Binding

```typescript signal-input.component.ts theme={null}
import { Component, model } from '@angular/core';

@Component({
  selector: 'app-signal-input',
  standalone: true,
  template: `
    <input 
      [value]="value()" 
      (input)="value.set($any($event.target).value)">
  `
})
export class SignalInputComponent {
  value = model('');
}
```

Usage:

```html theme={null}
<app-signal-input [(value)]="username"></app-signal-input>
```

## Parent-Child Communication Example

```typescript parent.component.ts theme={null}
import { Component } from '@angular/core';
import { ChildComponent } from './child.component';

@Component({
  selector: 'app-parent',
  standalone: true,
  imports: [ChildComponent],
  template: `
    <div>
      <h2>Parent Component</h2>
      <p>Message from child: {{childMessage}}</p>
      
      <app-child
        [parentMessage]="parentMessage"
        (messageToParent)="receiveMessage($event)">
      </app-child>
    </div>
  `
})
export class ParentComponent {
  parentMessage = 'Hello from parent';
  childMessage = '';

  receiveMessage(message: string) {
    this.childMessage = message;
  }
}
```

```typescript child.component.ts theme={null}
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  standalone: true,
  template: `
    <div>
      <h3>Child Component</h3>
      <p>{{parentMessage}}</p>
      <button (click)="sendMessage()">Send to Parent</button>
    </div>
  `
})
export class ChildComponent {
  @Input() parentMessage: string = '';
  @Output() messageToParent = new EventEmitter<string>();

  sendMessage() {
    this.messageToParent.emit('Hello from child');
  }
}
```

## Best Practices

<Tip>
  * Use signal inputs (`input()`) for new code - they're more performant
  * Mark inputs as `required` when they're essential for component function
  * Use input transforms for common conversions (boolean, number)
  * Prefer descriptive event names for outputs (e.g., `userSelected` over `select`)
  * Use TypeScript types for output events to ensure type safety
</Tip>

<Warning>
  * Don't mutate input objects - create new objects instead
  * Always complete EventEmitters in ngOnDestroy if they're long-lived
  * Avoid complex logic in input setters
  * Don't emit outputs in ngOnInit or constructor
</Warning>

## Comparison: Decorator vs Function

| Feature          | @Input / @Output | input() / output() |
| ---------------- | ---------------- | ------------------ |
| Type             | Decorator        | Function           |
| Reactivity       | Manual           | Signal-based       |
| Required inputs  | Via option       | Built-in support   |
| Transform        | Via option       | Via option         |
| Change detection | Zone.js          | Signals            |
| Performance      | Standard         | Better             |

## Related APIs

* [@Component](/api/core/component) - Define components
* [EventEmitter](/api/core/event-emitter) - Emit custom events
* [model()](/api/core/model) - Two-way binding with signals
* [computed()](/api/core/computed) - Derived signal values

## See Also

<CardGroup cols={2}>
  <Card title="Component Inputs" icon="book" href="/api/core/input-output">
    Learn about input properties
  </Card>

  <Card title="Component Outputs" icon="book" href="/api/core/input-output">
    Master output events
  </Card>

  <Card title="Signals" icon="book" href="/advanced/signals">
    Understand signal reactivity
  </Card>

  <Card title="Two-Way Binding" icon="book" href="/concepts/templates">
    Implement two-way binding
  </Card>
</CardGroup>
