Skip to main content
The SpeechPanelComponent provides a user interface for speech recognition and text-to-speech capabilities. It acts as a control panel with buttons for starting/stopping voice recognition, speaking text, and clearing form content.

Overview

This standalone component offers:
  • Voice recognition controls (start/stop listening)
  • Text-to-speech functionality
  • Form clearing capability
  • Visual feedback during listening state
  • Error state handling

Component metadata

@Component({
  selector: 'app-speech-panel',
  templateUrl: './speech-panel.component.html',
  styleUrl: './speech-panel.component.css',
  standalone: true
})
Location: src/app/_components/speech-panel/speech-panel.component.ts:4-9
This is a standalone component and can be imported directly without a module declaration.

Properties

Icon assets

ListeningButtonIconOn: string = './assets/images/mic_on.gif';
ListeningButtonIconOff: string = './assets/images/mic_off.gif';
SpeakerIcon: string = './assets/images/speaker_on.gif';
clearFormIcon: string = './assets/images/clearForm.gif';
Location: speech-panel.component.ts:12-15 These properties define the paths to icon assets used in the control panel buttons.

Event emitters

@Output() clickEventSpeak = new EventEmitter<string>();
Emits when the speak button is clicked, passing the text to be spoken.Location: speech-panel.component.ts:16

Constructor

Injects the SpeechService for speech functionality:
constructor(public speechService: SpeechService) {}
Location: speech-panel.component.ts:19-22

Methods

speakText()

Triggers text-to-speech functionality and emits the spoken text to the parent component.
speakText(): void
Location: speech-panel.component.ts:24-30
speakText(): void {
  this.clickEventSpeak.emit(this.speechService.speakText());
}
Process:
1

Invoke speech service

Calls speechService.speakText() to speak the current text
2

Emit event

Emits the text through clickEventSpeak for parent component handling

clearText()

Emits an event to clear form text in the parent component.
clearText(): void
Location: speech-panel.component.ts:32-37
clearText(): void {
  this.clickEventClearText.emit();
}

Template structure

The component renders a control panel with four buttons and status feedback:
<div>
  <button (click)="this.speechService.startListening()" [disabled]="this.speechService.isListening">
    <img class="imgSearch" [src]="this.ListeningButtonIconOn">
  </button>
  
  <button (click)="this.speechService.stopListening()" [disabled]="!this.speechService.isListening">
    <img class="imgSearch" [src]="this.ListeningButtonIconOff">
  </button>
  
  <button (click)="this.speakText()" [disabled]="this.speechService.isListening">
    <img class="imgSearch" [src]="this.SpeakerIcon">
  </button>
  
  <button (click)="this.clearText()">
    <img class="imgSearch" [src]="this.clearFormIcon" alt="new search">
  </button>
</div>
Location: speech-panel.component.html:1-6

Button states

Start listening

Disabled when speechService.isListening is true

Stop listening

Disabled when speechService.isListening is false

Speak text

Disabled when speechService.isListening is true

Clear form

Always enabled

Status feedback

The template displays real-time status information:
<div>
  @if ((this.speechService.isListening) && (!this.speechService.error)) {
    <span class="col col-form-label">[Listening...]</span>
  }
  
  @if (this.speechService.error) {
    <span class="col col-form-label" class="error">
      <p>Error: {{ this.speechService.error }}</p>
    </span>
  }
</div>
Location: speech-panel.component.html:7-16
The template uses Angular’s new control flow syntax (@if) for conditional rendering.

Usage

Importing the component

Since this is a standalone component, import it directly:
import { SpeechPanelComponent } from './path/to/speech-panel/speech-panel.component';

@Component({
  selector: 'app-my-component',
  standalone: true,
  imports: [SpeechPanelComponent],
  // ...
})
export class MyComponent {
  // ...
}

Using in templates

<app-speech-panel
  (clickEventSpeak)="onSpeakText($event)"
  (clickEventClearText)="onClearText()">
</app-speech-panel>

Handling events in parent component

export class ParentComponent {
  onSpeakText(text: string): void {
    console.log('Speaking:', text);
    // Handle spoken text
  }
  
  onClearText(): void {
    // Clear form fields or reset state
    this.formData = '';
  }
}

Integration example

Complete example showing integration with a form:
import { Component } from '@angular/core';
import { SpeechPanelComponent } from './speech-panel/speech-panel.component';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-search-form',
  standalone: true,
  imports: [SpeechPanelComponent, FormsModule],
  template: `
    <div class="search-container">
      <input [(ngModel)]="searchText" type="text" placeholder="Enter search query">
      
      <app-speech-panel
        (clickEventSpeak)="handleSpeak($event)"
        (clickEventClearText)="handleClear()">
      </app-speech-panel>
      
      <button (click)="search()">Search</button>
    </div>
  `
})
export class SearchFormComponent {
  searchText: string = '';
  
  handleSpeak(text: string): void {
    console.log('Spoken text:', text);
    // Optionally update searchText with spoken content
  }
  
  handleClear(): void {
    this.searchText = '';
  }
  
  search(): void {
    console.log('Searching for:', this.searchText);
    // Perform search
  }
}

SpeechService integration

The component relies on the SpeechService for core functionality:

Service properties

interface SpeechService {
  isListening: boolean;        // Current listening state
  error: string | null;        // Error message if any
  
  startListening(): void;      // Start voice recognition
  stopListening(): void;       // Stop voice recognition
  speakText(): string;         // Speak and return current text
}

State management

The component’s UI automatically reflects the service state:
// Start button disabled when listening
[disabled]="this.speechService.isListening"

// Stop button disabled when not listening
[disabled]="!this.speechService.isListening"

// Speak button disabled during listening
[disabled]="this.speechService.isListening"

Styling considerations

The component uses these CSS classes:
  • .imgSearch - Applied to button images
  • .col.col-form-label - Status text styling
  • .error - Error message styling
Customize these in your global styles or component styles:
.imgSearch {
  width: 32px;
  height: 32px;
  cursor: pointer;
}

.col-form-label {
  font-size: 14px;
  color: #333;
}

.error {
  color: #dc3545;
  font-weight: bold;
}

Accessibility

All buttons are keyboard-accessible through standard tab navigation and can be activated with Enter or Space keys.
Add aria-label attributes to buttons for better screen reader support:
<button 
  (click)="speechService.startListening()" 
  [disabled]="speechService.isListening"
  aria-label="Start voice recognition">
  <img [src]="ListeningButtonIconOn" alt="Start listening">
</button>
The component provides visual feedback through:
  • Disabled button states
  • Status text display
  • Animated GIF icons (when listening)

Use cases

The SpeechPanelComponent is ideal for:

Search forms

Voice-enabled search interfaces

Data entry

Hands-free form filling

Accessibility

Alternative input methods for users with disabilities

Mobile apps

Touch-friendly voice controls

Build docs developers (and LLMs) love