Skip to main content

Overview

The QuestSharedService is a lightweight event coordination service that enables communication between different components in the Tareas application. It uses RxJS observables to notify components when quest data should be refreshed.

Use Case

This service is particularly useful when one component modifies quest data (e.g., creating or updating a quest) and other components need to refresh their view to display the latest data.

Features

  • Simple event-based refresh mechanism
  • Observable-based architecture using RxJS
  • Decoupled component communication
  • Singleton service (providedIn: ‘root’)

Observable Streams

refresh$

An observable stream that emits whenever a quest refresh should be triggered.
refresh$: Observable<void>
Observable<void>
Observable
Observable stream that emits void values. Subscribe to this stream to receive refresh notifications.

Usage Example

import { QuestSharedService } from './common/services/questshared.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-quest-list',
  templateUrl: './quest-list.component.html'
})
export class QuestListComponent implements OnInit, OnDestroy {
  private refreshSubscription: Subscription;

  constructor(private questSharedService: QuestSharedService) {}

  ngOnInit() {
    // Listen for refresh events
    this.refreshSubscription = this.questSharedService.refresh$.subscribe(() => {
      console.log('Refresh triggered - reloading quests');
      this.loadQuests();
    });
  }

  ngOnDestroy() {
    // Clean up subscription
    this.refreshSubscription?.unsubscribe();
  }

  loadQuests() {
    // Reload quest data
    console.log('Loading fresh quest data...');
  }
}

Methods

triggerRefresh()

Triggers a refresh event that notifies all subscribers to reload their quest data.
triggerRefresh(): void
void
void
This method does not return a value. It emits a refresh event to all refresh$ subscribers.

Usage Example

import { QuestSharedService } from './common/services/questshared.service';
import { Component } from '@angular/core';

@Component({
  selector: 'app-create-quest',
  templateUrl: './create-quest.component.html'
})
export class CreateQuestComponent {
  constructor(private questSharedService: QuestSharedService) {}

  async createQuest(questData: any) {
    // Save the new quest
    await this.saveQuestToDatabase(questData);

    console.log('Quest created successfully');

    // Notify other components to refresh their quest lists
    this.questSharedService.triggerRefresh();

    // Navigate back or close modal
    this.closeModal();
  }

  private async saveQuestToDatabase(questData: any): Promise<void> {
    // Database save logic
  }

  private closeModal(): void {
    // Modal close logic
  }
}

Common Patterns

Pattern 1: Create-and-Refresh Workflow

When creating a new quest, trigger a refresh to update all quest lists:
import { QuestSharedService } from './common/services/questshared.service';
import { Component } from '@angular/core';

@Component({
  selector: 'app-quest-form',
  templateUrl: './quest-form.component.html'
})
export class QuestFormComponent {
  constructor(private questSharedService: QuestSharedService) {}

  onSubmit(quest: Quest) {
    // 1. Save the quest
    this.questService.createQuest(quest).then(() => {
      // 2. Trigger refresh across all components
      this.questSharedService.triggerRefresh();
      
      // 3. Show success message
      this.showToast('Quest created successfully!');
    });
  }
}

Pattern 2: Multi-Component Coordination

Coordinate updates between multiple views:
// Component that displays quests
import { Component, OnInit, OnDestroy } from '@angular/core';
import { QuestSharedService } from './common/services/questshared.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-quest-list',
  templateUrl: './quest-list.component.html'
})
export class QuestListComponent implements OnInit, OnDestroy {
  quests: Quest[] = [];
  private refreshSub: Subscription;

  constructor(
    private questService: QuestService,
    private questSharedService: QuestSharedService
  ) {}

  ngOnInit() {
    this.loadQuests();
    
    // Subscribe to refresh events
    this.refreshSub = this.questSharedService.refresh$.subscribe(() => {
      this.loadQuests();
    });
  }

  loadQuests() {
    this.questService.getQuests().subscribe(quests => {
      this.quests = quests;
    });
  }

  ngOnDestroy() {
    this.refreshSub?.unsubscribe();
  }
}

Pattern 3: Complete Quest Workflow

Handle quest completion with automatic UI updates:
import { Component } from '@angular/core';
import { QuestSharedService } from './common/services/questshared.service';

@Component({
  selector: 'app-quest-card',
  templateUrl: './quest-card.component.html'
})
export class QuestCardComponent {
  constructor(
    private questService: QuestService,
    private questSharedService: QuestSharedService
  ) {}

  async completeQuest(quest: Quest) {
    // Mark quest as completed
    await this.questService.completeQuest(quest.id);

    // Show completion animation/reward
    await this.showCompletionAnimation();

    // Trigger refresh to update all quest lists
    this.questSharedService.triggerRefresh();

    // Show reward notification
    this.showRewardNotification(quest.xpReward);
  }

  private async showCompletionAnimation(): Promise<void> {
    // Animation logic
  }

  private showRewardNotification(xp: number): void {
    console.log(`You earned ${xp} XP!`);
  }
}

Architecture Notes

The service uses a BehaviorSubject internally, which means:
  • New subscribers receive the latest value immediately (initially undefined)
  • All subscribers are notified when triggerRefresh() is called
  • The subject is exposed as an observable (refresh$) to prevent external modifications
Always remember to unsubscribe from refresh$ in your component’s ngOnDestroy() to prevent memory leaks.

When to Use

Use QuestSharedService when:
  • A component creates, updates, or deletes a quest
  • Multiple components display quest data and need to stay synchronized
  • You want to decouple components that modify data from components that display data
  • You need a lightweight event bus for quest-related updates
This service only triggers refresh events. It does not store or manage quest data itself. Use QuestService for actual quest data management.

Build docs developers (and LLMs) love